<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>安全数据清洗</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: 'rgba(59, 130, 246, 0.96)',
                        light: 'rgba(255, 255, 255, 0.96)',
                        mid: 'rgba(255, 255, 255, 0.92)',
                        dark: 'rgba(51, 65, 85, 0.96)',
                        hover: 'rgba(59, 130, 246, 0.15)',
                        border: 'rgba(59, 130, 246, 0.4)',
                        bg: 'rgba(248, 250, 252, 0.96)',
                        accent: 'rgba(59, 130, 246, 0.15)',
                        text: {
                            primary: '#334155',
                            secondary: '#64748b'
                        }
                    },
                    borderRadius: {
                        'sm': '8px',
                        'md': '12px',
                        'full': '50%'
                    },
                    boxShadow: {
                        'default': '0 4px 12px rgba(0,0,0,0.02)',
                        'hover': '0 6px 16px rgba(0,0,0,0.04)'
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-balance {
                text-wrap: balance;
            }
            /* 背景网格效果 */
            .bg-grid {
                background-image: radial-gradient(rgba(59, 130, 246, 0.05) 1px, transparent 1px);
                background-size: 20px 20px;
                background-position: 0 0;
            }
            
            /* 色彩系统应用 */
            .color-main {
                color: rgba(59, 130, 246, 0.96);
            }
            .color-text-primary {
                color: #334155;
            }
            .color-text-secondary {
                color: #64748b;
            }
            .border-color-main {
                border-color: rgba(59, 130, 246, 0.4);
            }
            
            /* 排版规范 */
            .text-gradient {
                background: linear-gradient(135deg, rgba(59, 130, 246, 0.96), #334155);
                -webkit-background-clip: text;
                -webkit-text-fill-color: transparent;
                background-clip: text;
            }
            .text-heading-lg {
                font-size: clamp(1.5rem, 3vw, 2rem);
                font-weight: 700;
                line-height: 1.2;
            }
            .text-heading-md {
                font-size: 1.125rem; /* text-lg */
                font-weight: 600;
                line-height: 1.3;
            }
            .text-heading-sm {
                font-size: 0.875rem; /* text-sm */
                font-weight: 500;
                line-height: 1.4;
            }
            .text-body {
                line-height: 1.5;
            }
            .text-caption {
                font-size: 0.75rem; /* text-xs */
                line-height: 1.5;
            }
            /* 交互设计效果 */
            .smooth-transition {
                transition: all 0.3s ease;
            }
            
            /* 卡片悬停效果 */
            .card-hover {
                transition: transform 0.25s ease, box-shadow 0.25s ease;
            }
            .card-hover:hover {
                transform: translateY(-2px);
                box-shadow: 0 6px 16px rgba(0,0,0,0.04);
            }
            
            /* 玻璃态效果 */
            .glass-effect {
                backdrop-filter: blur(20px);
                background-color: rgba(255, 255, 255, 0.8);
            }
            
            /* 激活状态指示 */
            .active-indicator {
                position: relative;
                padding-left: 0.75rem;
            }
            .active-indicator::before {
                content: '';
                position: absolute;
                left: 0;
                top: 50%;
                transform: translateY(-50%);
                width: 3px;
                height: 70%;
                background-color: rgba(59, 130, 246, 0.96);
                border-radius: 0 4px 4px 0;
            }
            
            /* 表单输入样式 */
            .form-input {
                border: 1px solid rgba(59, 130, 246, 0.4);
                background-color: rgba(255, 255, 255, 0.9);
                border-radius: 0.5rem;
                padding: 0.5rem 0.75rem;
                font-size: 0.875rem;
                color: #334155;
                transition: all 0.2s ease;
            }
            .form-input:focus {
                outline: none;
                box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
                border-color: transparent;
            }
            
            /* 按钮样式 */
            .btn-primary {
                background-color: rgba(59, 130, 246, 0.96);
                color: white;
                padding: 0.5rem 1rem;
                border-radius: 0.5rem;
                transition: background-color 0.3s ease;
            }
            .btn-primary:hover {
                background-color: rgba(59, 130, 246, 0.85);
            }
            
            .btn-secondary {
                background-color: rgba(255, 255, 255, 0.96);
                border: 1px solid rgba(59, 130, 246, 0.4);
                color: #334155;
                padding: 0.5rem 1rem;
                border-radius: 0.5rem;
                transition: all 0.3s ease;
            }
            .btn-secondary:hover {
                background-color: rgba(59, 130, 246, 0.15);
                border-color: rgba(59, 130, 246, 0.6);
            }
            /* 微妙的悬浮动画 */
            .float-animation {
                animation: float 3s ease-in-out infinite;
            }
            @keyframes float {
                0% { transform: translateY(0px); }
                50% { transform: translateY(-4px); }
                100% { transform: translateY(0px); }
            }
            /* 通知点脉冲效果 */
            .pulse-effect {
                animation: pulse 2s infinite;
            }
            @keyframes pulse {
                0% {
                    box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
                }
                70% {
                    box-shadow: 0 0 0 10px rgba(59, 130, 246, 0);
                }
                100% {
                    box-shadow: 0 0 0 0 rgba(59, 130, 246, 0);
                }
            }
            /* 平滑过渡 */
            .smooth-transition {
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            }
            /* 表格行悬停效果 */
            .table-row-hover {
                transition: background-color 0.15s ease;
            }
            .table-row-hover:hover {
                background-color: rgba(59, 130, 246, 0.05);
            }
            /* 模态框淡入效果 */
            .modal-transition {
                transition: opacity 0.2s ease, transform 0.2s ease;
            }
            /* 通知滑入效果 */
            .notification-slide {
                transform: translateY(10px);
                opacity: 0;
                transition: transform 0.3s ease, opacity 0.3s ease;
            }
            .notification-slide.show {
                transform: translateY(0);
                opacity: 1;
            }
            /* 输入框聚焦效果 */
            .input-focus {
                transition: border-color 0.3s ease, box-shadow 0.3s ease;
            }
            .input-focus:focus {
                border-color: theme('colors.primary');
                box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
                outline: none;
            }
            
            /* 规则构建器样式 */
            .rule-tab {
                @apply px-4 py-2 rounded-md smooth-transition cursor-pointer border border-transparent;
            }
            .rule-tab.active {
                @apply bg-hover text-primary border border-border;
            }
            .rule-tab:hover:not(.active) {
                @apply bg-hover/50;
            }
            
            .rule-type-btn {
                @apply px-4 py-2 rounded-md bg-light border border-border text-text-primary hover:bg-hover smooth-transition;
            }
            .rule-type-btn:hover {
                @apply border-primary transform -translate-y-0.5 shadow-sm;
            }
            
            .rule-item {
                @apply bg-light border border-border rounded-md p-4 mb-4 smooth-transition relative overflow-hidden;
            }
            .rule-item:hover {
                @apply border-primary shadow-sm;
            }
            .rule-item::before {
                content: '';
                @apply absolute left-0 top-0 bottom-0 w-[3px] bg-transparent transition-all duration-300;
            }
            .rule-item:hover::before {
                @apply bg-primary;
            }
            
            .rule-field {
                @apply border border-border rounded-md px-3 py-2 w-full input-focus bg-light/80;
            }
            
            .rule-condition {
                @apply bg-light border border-border rounded-md p-3 mb-2;
            }
            
            .rule-config-section {
                @apply bg-mid border border-border rounded-md p-4 mb-4;
            }
            
            .code-editor-container {
                @apply bg-dark/90 rounded-md p-4 text-white font-mono text-sm min-h-[200px] overflow-auto;
            }
            
            .rule-action-btn {
                @apply p-1.5 rounded-md text-text-secondary hover:text-primary hover:bg-hover smooth-transition;
            }
            .rule-action-btn.danger:hover {
                @apply text-red-500 bg-red-50;
            }
            
            .add-rule-btn {
                @apply bg-light border border-border text-primary hover:bg-hover smooth-transition transform hover:-translate-y-0.5;
            }
            
            /* 运行按钮样式 */
            .run-task-btn {
                @apply bg-green-100 text-green-600 border border-green-200 px-3 py-1.5 rounded-md text-sm font-medium hover:bg-green-600 hover:text-white smooth-transition transform hover:-translate-y-0.5;
            }
            
            /* 加载动画 */
            .spinner {
                @apply w-5 h-5 border-2 border-transparent border-t-primary rounded-full animate-spin inline-block;
            }
            
            @keyframes spin {
                from { transform: rotate(0deg); }
                to { transform: rotate(360deg); }
            }
        }
    /* 加载动画样式 */
            .btn-loading {
                opacity: 0.7;
                cursor: not-allowed;
            }
            
            .btn-loading i {
                animation: spin 0.8s linear infinite;
            }
            
            @keyframes spin {
                to {
                    transform: rotate(360deg);
                }
            }
        </style>
</head>
<body class="bg-bg min-h-screen text-text-primary overflow-x-hidden">
    <!-- 背景网格层 -->
    <article class="fixed inset-0 bg-grid pointer-events-none z-0"></article>
    
    <!-- 独立标题header层 -->
    <header class="fixed top-5 left-5 right-5 z-10 bg-light border border-border rounded-md shadow-sm p-5" style="backdrop-filter: blur(20px); background: linear-gradient(135deg, rgba(255,255,255,0.92), rgba(252,254,255,0.92));">
        <h1 class="text-heading-lg text-[#334155] tracking-[-0.5px]">安全数据清洗</h1>
    </header>
    
    <!-- 主内容main层 -->
    <main class="absolute top-[calc(8rem+5px)] left-5 right-5 p-5 bg-light rounded-md shadow-sm border border-border z-10 min-h-[calc(100vh-8rem-60px)]" style="width: calc(100% - 40px);">
        <!-- 导航标签 -->
        <div class="mb-6">
            <div class="flex border-b border-border-color-main">
                <button id="tab-tasks" class="nav-tab py-3 px-5 font-medium text-primary border-b-2 border-primary -mb-[1px] rounded-t-md smooth-transition active-indicator" data-target="tasks-panel">
                    <i class="fa fa-tasks mr-2"></i>任务管理
                </button>
                <button id="tab-scheduling" class="nav-tab py-3 px-5 font-medium text-text-secondary hover:bg-hover hover:text-primary smooth-transition" data-target="scheduling-panel">
                    <i class="fa fa-calendar-check-o mr-2"></i>任务调度
                </button>
                <button id="tab-logs" class="nav-tab py-3 px-5 font-medium text-text-secondary hover:bg-hover hover:text-primary smooth-transition" data-target="logs-panel">
                    <i class="fa fa-history mr-2"></i>日志查看
                </button>
            </div>
        </div>

        <!-- 主内容区域 -->
        <main>
            <!-- 任务管理面板 -->
            <div id="tasks-panel" class="tab-panel">
                <div class="bg-light rounded-md shadow-default p-6 mb-6">
                    <div class="flex flex-wrap justify-between items-center mb-4">
                        <h2 class="text-heading-md">数据处理任务</h2>
                        <button id="add-task-btn" class="btn-primary px-4 py-2 rounded-md smooth-transition flex items-center">
                            <i class="fa fa-plus mr-2"></i>添加任务
                        </button>
                    </div>
                    
                    <!-- 搜索和过滤 -->
                    <div class="flex flex-wrap gap-4 mb-4">
                        <div class="relative flex-grow max-w-md">
                            <input type="text" id="task-search" placeholder="搜索任务名称" class="w-full px-4 py-2 pl-10 border border-border rounded-md bg-mid input-focus">
                            <i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-text-secondary"></i>
                        </div>
                        <select id="task-status-filter" class="px-4 py-2 border border-border rounded-md bg-mid input-focus">
                            <option value="all">所有状态</option>
                            <option value="enabled">已启用</option>
                            <option value="disabled">已禁用</option>
                        </select>
                    </div>
                    
                    <!-- 任务列表 -->
                    <div id="tasks-list" class="overflow-x-auto">
                        <table class="min-w-full">
                            <thead>
                                <tr class="bg-gray-50 bg-opacity-50">
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">任务名称</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">描述</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">部署状态</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">创建时间</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">状态</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">操作</th>
                                </tr>
                            </thead>
                            <tbody id="tasks-table-body">
                                <!-- 任务列表将通过JavaScript动态生成 -->
                            </tbody>
                        </table>
                    </div>
                    
                    <!-- 空状态提示 -->
                    <div id="tasks-empty-state" class="text-center py-12 hidden">
                        <i class="fa fa-tasks text-4xl text-text-secondary/30 mb-4"></i>
                        <p class="text-text-secondary">暂无任务，请添加新任务</p>
                    </div>
                </div>
            </div>

            <!-- 任务调度面板 -->
            <div id="scheduling-panel" class="tab-panel hidden">
                <div class="bg-light rounded-md shadow-default p-6 mb-6">
                    <div class="flex flex-wrap justify-between items-center mb-4">
                        <h2 class="text-lg font-semibold">任务调度配置</h2>
                        <button id="add-schedule-btn" class="bg-primary text-white px-4 py-2 rounded-md hover:bg-opacity-90 smooth-transition flex items-center">
                            <i class="fa fa-plus mr-2"></i>添加调度
                        </button>
                    </div>
                    
                    <!-- 调度列表 -->
                    <div id="schedules-list" class="overflow-x-auto">
                        <table class="min-w-full">
                            <thead>
                                <tr class="bg-gray-50 bg-opacity-50">
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">调度名称</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">关联任务</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">调度类型</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">表达式</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">状态</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">最后执行时间</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">下次执行时间</th>
                                    <th class="px-4 py-3 text-left text-sm font-medium text-text-secondary">操作</th>
                                </tr>
                            </thead>
                            <tbody id="schedules-table-body">
                                <!-- 调度列表将通过JavaScript动态生成 -->
                            </tbody>
                        </table>
                    </div>
                    
                    <!-- 空状态提示 -->
                    <div id="schedules-empty-state" class="text-center py-12 hidden">
                        <i class="fa fa-calendar text-4xl text-text-secondary/30 mb-4"></i>
                        <p class="text-text-secondary">暂无调度配置，请添加新调度</p>
                    </div>
                </div>
            </div>

            <!-- 日志查看面板 -->
            <div id="logs-panel" class="tab-panel hidden">
                <div class="bg-light rounded-md shadow-default p-6 mb-6">
                    <div class="flex flex-wrap justify-between items-center mb-4">
                        <h2 class="text-lg font-semibold">操作日志</h2>
                    </div>
                    
                    <!-- 日志过滤 -->
                    <div class="flex flex-wrap gap-4 mb-4 bg-mid p-3 rounded-lg">
                        <select id="log-task-filter" class="px-4 py-2 border border-border rounded-md bg-light input-focus">
                            <option value="">所有任务</option>
                            <!-- 任务选项将通过JavaScript动态生成 -->
                        </select>
                        <input type="date" id="log-date-filter" class="px-4 py-2 border border-border rounded-md bg-light input-focus">
                        <select id="log-level-filter" class="px-4 py-2 border border-border rounded-md bg-light input-focus">
                            <option value="">所有级别</option>
                            <option value="info">信息</option>
                            <option value="success">成功</option>
                            <option value="warning">警告</option>
                            <option value="error">错误</option>
                        </select>
                        <div class="relative">
                            <i class="fa fa-search absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary"></i>
                            <input type="text" id="log-search" placeholder="搜索日志内容" class="px-9 py-2 border border-border rounded-md bg-light input-focus">
                        </div>
                        <button id="refresh-logs" class="px-4 py-2 border border-primary/30 rounded-md hover:bg-primary/5 smooth-transition text-primary">
                            <i class="fa fa-refresh mr-2"></i>刷新
                        </button>
                        <button id="clear-log-filter" class="px-4 py-2 border border-primary/30 rounded-md hover:bg-primary/5 smooth-transition text-primary">
                            <i class="fa fa-filter mr-2"></i>清除过滤
                        </button>
                    </div>
                    
                    <!-- 日志内容 -->
                    <div id="logs-content" class="max-h-[500px] overflow-y-auto p-4 bg-mid rounded-md">
                        <!-- 日志内容将通过JavaScript动态生成 -->
                        <p class="text-text-secondary text-center">加载日志中...</p>
                    </div>
                </div>
            </div>
</main>
    
    <!-- 任务编辑模态框 -->
    <div id="task-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
        <div class="bg-light rounded-md shadow-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto modal-transition">
            <div class="p-6 border-b border-border">
                <div class="flex justify-between items-center">
                    <h3 id="task-modal-title" class="text-lg font-semibold">添加任务</h3>
                    <button id="close-task-modal" class="text-text-secondary hover:text-dark">
                        <i class="fa fa-times text-xl"></i>
                    </button>
                </div>
            </div>
            <div class="p-6">
                <form id="task-form">
                    <input type="hidden" id="task-id">
                    <div class="mb-4">
                        <label for="task-name" class="block text-sm font-medium mb-1">任务名称 <span class="text-red-500">*</span></label>
                        <input type="text" id="task-name" class="w-full px-4 py-2 border border-border rounded-md input-focus" required>
                    </div>
                    <div class="mb-4">
                        <label for="task-description" class="block text-sm font-medium mb-1">任务描述</label>
                        <textarea id="task-description" rows="3" class="w-full px-4 py-2 border border-border rounded-md input-focus"></textarea>
                    </div>
                    <div class="mb-4">
                        <label for="task-rules" class="block text-sm font-medium mb-1">清洗规则配置 <span class="text-red-500">*</span></label>
                        <!-- 规则构建器选项卡 -->
                        <div class="border border-border rounded-md overflow-hidden mb-2">
                            <div class="flex border-b border-border">
                                <button type="button" class="rule-tab active px-4 py-2 text-sm font-medium" data-tab="builder">
                                    <i class="fa fa-wrench mr-2"></i>规则构建器
                                </button>
                                <button type="button" class="rule-tab px-4 py-2 text-sm font-medium text-text-secondary" data-tab="json">
                                    <i class="fa fa-code mr-2"></i>JSON编辑
                                </button>
                            </div>
                            
                            <!-- 规则构建器面板 -->
                            <div id="rule-builder-panel" class="p-4">
                                <div class="mb-6">
                                    <label class="block text-sm font-medium mb-3 text-text-primary">选择规则类型</label>
                                    <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
                                        <button type="button" class="rule-type-btn flex items-center justify-center" data-rule-type="null_check">
                                            <i class="fa fa-ban mr-2 text-primary"></i>
                                            <span>空值检查</span>
                                        </button>
                                        <button type="button" class="rule-type-btn flex items-center justify-center" data-rule-type="ip_validation">
                                            <i class="fa fa-globe mr-2 text-primary"></i>
                                            <span>IP验证</span>
                                        </button>
                                        <button type="button" class="rule-type-btn flex items-center justify-center" data-rule-type="timestamp_normalization">
                                            <i class="fa fa-clock-o mr-2 text-primary"></i>
                                            <span>时间标准化</span>
                                        </button>
                                        <button type="button" class="rule-type-btn flex items-center justify-center" data-rule-type="data_masking">
                                            <i class="fa fa-eye-slash mr-2 text-primary"></i>
                                            <span>数据脱敏</span>
                                        </button>
                                        <button type="button" class="rule-type-btn flex items-center justify-center" data-rule-type="format_conversion">
                                            <i class="fa fa-exchange mr-2 text-primary"></i>
                                            <span>格式转换</span>
                                        </button>
                                    </div>
                                </div>
                                
                                <div class="mb-4">
                                    <label class="block text-sm font-medium mb-3 text-text-primary">已添加规则</label>
                                    <div id="rules-list" class="rule-config-section max-h-72 overflow-y-auto p-3">
                                        <!-- 规则列表将动态生成 -->
                                        <div class="text-center text-text-secondary text-sm py-6">
                                            <i class="fa fa-list-ul text-2xl mb-2 opacity-50 float-animation"></i>
                                            <p>暂无规则，请添加规则</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            
                            <!-- JSON编辑器面板 -->
                            <div id="rule-json-panel" class="hidden">
                                <div class="mb-2">
                                    <label class="block text-sm font-medium mb-2 text-text-primary">规则JSON</label>
                                    <div class="code-editor-container">
                                        <textarea id="task-rules" rows="8" class="w-full bg-transparent border-0 text-white focus:outline-none font-mono text-sm resize-none" placeholder='{"rules":[]}' required></textarea>
                                    </div>
                                </div>
                                <div class="mt-3 flex flex-wrap justify-between items-center text-xs text-text-secondary gap-2">
                                    <span class="flex items-center"><i class="fa fa-info-circle mr-1"></i> 请确保JSON格式正确</span>
                                    <button type="button" id="format-json-btn" class="text-primary hover:underline flex items-center">
                                        <i class="fa fa-indent mr-1"></i> 格式化
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="mb-4">
                        <label class="flex items-center">
                            <input type="checkbox" id="task-enabled" class="form-checkbox text-primary rounded">
                            <span class="ml-2 text-sm">启用任务</span>
                        </label>
                    </div>
                </form>
            </div>
            <div class="p-6 border-t border-border flex justify-end gap-3">
                <button id="cancel-task-btn" class="btn-secondary px-4 py-2 text-sm font-medium">
                                <i class="fa fa-times mr-1.5"></i>取消
                            </button>
                            <button id="save-task-btn" class="btn-primary px-4 py-2 text-sm font-medium">
                                <i class="fa fa-check mr-1.5"></i>保存
                            </button>
            </div>
        </div>
    </div>

    <!-- 调度编辑模态框 -->
    <div id="schedule-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
        <div class="bg-light rounded-md shadow-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto modal-transition">
            <div class="p-6 border-b border-border">
                <div class="flex justify-between items-center">
                    <h3 id="schedule-modal-title" class="text-lg font-semibold">添加调度</h3>
                    <button id="close-schedule-modal" class="text-text-secondary hover:text-dark">
                        <i class="fa fa-times text-xl"></i>
                    </button>
                </div>
            </div>
            <div class="p-6">
                <form id="schedule-form">
                    <input type="hidden" id="schedule-id">
                    <div class="mb-4">
                        <label for="schedule-name" class="block text-sm font-medium mb-1">调度名称 <span class="text-red-500">*</span></label>
                        <input type="text" id="schedule-name" class="w-full px-4 py-2 border border-border rounded-md input-focus" required>
                    </div>
                    <div class="mb-4">
                        <label for="schedule-task" class="block text-sm font-medium mb-1">关联任务 <span class="text-red-500">*</span></label>
                        <select id="schedule-task" class="w-full px-4 py-2 border border-border rounded-md input-focus" required>
                            <option value="">请选择任务</option>
                            <!-- 任务选项将通过JavaScript动态生成 -->
                        </select>
                    </div>
                    <div class="mb-4">
                        <label for="schedule-type" class="block text-sm font-medium mb-1">调度类型 <span class="text-red-500">*</span></label>
                        <select id="schedule-type" class="w-full px-4 py-2 border border-border rounded-md input-focus" required>
                            <option value="cron">Cron表达式</option>
                            <option value="interval">固定间隔</option>
                        </select>
                    </div>
                    <div class="mb-4">
                        <label for="schedule-expression" class="block text-sm font-medium mb-1">调度表达式 <span class="text-red-500">*</span></label>
                        <input type="text" id="schedule-expression" class="w-full px-4 py-2 border border-border rounded-md input-focus" placeholder="如: 0 0/5 * * * ? 或 300(秒)" required>
                        <div id="schedule-expression-hint" class="text-xs text-text-secondary mt-1">Cron格式: 秒 分 时 日 月 周 年 或 间隔秒数</div>
                        <div id="schedule-next-execution" class="text-xs mt-1 hidden"></div>
                        <!-- 常用调度表达式快捷按钮 -->
                        <div class="mt-2 flex flex-wrap gap-2">
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="cron" data-expression="0 0 0 * * ?">每天凌晨</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="cron" data-expression="0 0 12 * * ?">每天中午</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="cron" data-expression="0 0 0 ? * MON">每周一凌晨</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="cron" data-expression="0 0 0 1 * ?">每月1号凌晨</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="interval" data-expression="300">每5分钟</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="interval" data-expression="1800">每30分钟</button>
                            <button type="button" class="schedule-quick-btn text-xs px-2 py-1 bg-mid rounded hover:bg-primary/10 smooth-transition" data-type="interval" data-expression="3600">每小时</button>
                        </div>
                    </div>
                    <div class="mb-4">
                        <label class="flex items-center">
                            <input type="checkbox" id="schedule-enabled" class="form-checkbox text-primary rounded">
                            <span class="ml-2 text-sm">启用调度</span>
                        </label>
                    </div>
                </form>
            </div>
            <div class="p-6 border-t border-border flex justify-end gap-3">
                <button id="cancel-schedule-btn" class="btn-secondary px-4 py-2 text-sm font-medium">
                                <i class="fa fa-times mr-1.5"></i>取消
                            </button>
                            <button id="save-schedule-btn" class="btn-primary px-4 py-2 text-sm font-medium">
                                <i class="fa fa-check mr-1.5"></i>保存
                            </button>
            </div>
        </div>
    </div>

    <!-- 调度详情模态框 -->
    <div id="schedule-details-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
        <div class="bg-light rounded-md shadow-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto modal-transition">
            <div class="p-6 border-b border-border">
                <div class="flex justify-between items-center">
                    <h3 id="schedule-details-title" class="text-lg font-semibold">调度详情</h3>
                    <button id="close-schedule-details-modal" class="text-text-secondary hover:text-dark">
                        <i class="fa fa-times text-xl"></i>
                    </button>
                </div>
            </div>
            <div class="p-6">
                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div class="col-span-1">
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">调度名称</label>
                            <div id="details-schedule-name" class="text-dark font-medium"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">关联任务</label>
                            <div id="details-schedule-task" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">调度类型</label>
                            <div id="details-schedule-type" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">调度表达式</label>
                            <div id="details-schedule-expression" class="text-dark font-mono bg-mid p-2 rounded"></div>
                        </div>
                    </div>
                    <div class="col-span-1">
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">状态</label>
                            <div id="details-schedule-status" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">下次执行时间</label>
                            <div id="details-next-execution" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">上次执行时间</label>
                            <div id="details-last-execution" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">创建时间</label>
                            <div id="details-created-at" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">更新时间</label>
                            <div id="details-updated-at" class="text-dark"></div>
                        </div>
                    </div>
                </div>
                <div class="mt-6">
                    <label class="block text-sm font-medium text-text-secondary mb-1">调度描述</label>
                    <div id="details-schedule-description" class="text-dark bg-mid p-3 rounded min-h-[100px]"></div>
                </div>
            </div>
            <div class="p-6 border-t border-border flex justify-end">
                <button id="close-schedule-details-btn" class="btn-primary px-4 py-2 text-sm font-medium">
                    <i class="fa fa-check mr-1.5"></i>关闭
                </button>
            </div>
        </div>
    </div>

    <!-- 日志详情模态框 -->
    <div id="log-details-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
        <div class="bg-light rounded-md shadow-lg max-w-3xl w-full max-h-[90vh] overflow-y-auto modal-transition">
            <div class="p-6 border-b border-border">
                <div class="flex justify-between items-center">
                    <h3 id="log-details-title" class="text-lg font-semibold">日志详情</h3>
                    <button id="close-log-details-modal" class="text-text-secondary hover:text-dark">
                        <i class="fa fa-times text-xl"></i>
                    </button>
                </div>
            </div>
            <div class="p-6">
                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div class="col-span-1">
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">任务名称</label>
                            <div id="details-log-task" class="text-dark font-medium"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">日志级别</label>
                            <div id="details-log-level" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">时间</label>
                            <div id="details-log-time" class="text-dark"></div>
                        </div>
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-text-secondary mb-1">日志ID</label>
                            <div id="details-log-id" class="text-dark font-mono text-xs"></div>
                        </div>
                    </div>
                </div>
                <div class="mt-6">
                    <label class="block text-sm font-medium text-text-secondary mb-1">日志内容</label>
                    <div id="details-log-message" class="text-dark bg-mid p-4 rounded-md whitespace-pre-wrap font-mono text-sm min-h-[200px]"></div>
                </div>
            </div>
            <div class="p-6 border-t border-border flex justify-end gap-3">
                <button id="copy-log-details-btn" class="btn-secondary px-4 py-2 text-sm font-medium">
                    <i class="fa fa-copy mr-1.5"></i>复制完整日志
                </button>
                <button id="close-log-details-btn" class="btn-primary px-4 py-2 text-sm font-medium">
                    <i class="fa fa-check mr-1.5"></i>关闭
                </button>
            </div>
        </div>
    </div>

    <script>
        // 使用纯JavaScript

        // 本地存储键名常量
        const STORAGE_KEYS = {
            TASKS: 'data_cleansing_tasks',
            SCHEDULES: 'data_cleansing_schedules',
            LOGS: 'data_cleansing_logs',
            PROCESSING_RESULTS: 'data_cleansing_results'
        };

        // 数据验证工具函数
        function validateTask(task) {
            return (
                task &&
                typeof task.id === 'string' &&
                typeof task.name === 'string' &&
                typeof task.description === 'string' &&
                typeof task.rules === 'string' &&
                typeof task.enabled === 'boolean' &&
                typeof task.deployed === 'boolean' &&
                typeof task.createdAt === 'string' &&
                typeof task.updatedAt === 'string'
            );
        }

        function validateSchedule(schedule) {
            return (
                schedule &&
                typeof schedule.id === 'string' &&
                typeof schedule.name === 'string' &&
                typeof schedule.taskId === 'string' &&
                (schedule.type === 'cron' || schedule.type === 'interval') &&
                typeof schedule.expression === 'string' &&
                typeof schedule.enabled === 'boolean' &&
                typeof schedule.createdAt === 'string' &&
                typeof schedule.updatedAt === 'string'
            );
        }

        // 本地存储操作工具
        function safeLocalStorageGet(key) {
            try {
                const data = localStorage.getItem(key);
                return data ? JSON.parse(data) : null;
            } catch (error) {
                console.error(`从本地存储获取数据失败 [${key}]:`, error);
                return null;
            }
        }

        function safeLocalStorageSet(key, data) {
            try {
                localStorage.setItem(key, JSON.stringify(data));
                return true;
            } catch (error) {
                console.error(`向本地存储保存数据失败 [${key}]:`, error);
                return false;
            }
        }

        class DataStorage {
            // 获取所有任务
            getTasks() {
                const data = safeLocalStorageGet(STORAGE_KEYS.TASKS);
                if (!Array.isArray(data)) {
                    return [];
                }
                // 验证并过滤有效任务数据
                return data.filter(task => validateTask(task));
            }

            // 添加任务
            saveTask(task) {
                if (!validateTask(task)) {
                    console.error('任务数据格式无效:', task);
                    throw new Error('任务数据格式无效');
                }

                try {
                    const tasks = this.getTasks();
                    const index = tasks.findIndex(t => t.id === task.id);
                    
                    task.updatedAt = new Date().toISOString();
                    
                    if (index >= 0) {
                        tasks[index] = task;
                    } else {
                        task.createdAt = new Date().toISOString();
                        task.deployed = task.deployed || false;
                        tasks.push(task);
                    }
                    
                    if (!safeLocalStorageSet(STORAGE_KEYS.TASKS, tasks)) {
                        throw new Error('保存任务到本地存储失败');
                    }
                    
                    this.addLog(task.id, task.name, `任务${index >= 0 ? '更新' : '创建'}成功: ${task.name}`);
                } catch (error) {
                    console.error('保存任务失败:', error);
                    throw error;
                }
            }

            // 删除任务
            deleteTask(id) {
                if (typeof id !== 'string') {
                    throw new Error('任务ID无效');
                }

                try {
                    const tasks = this.getTasks();
                    const task = tasks.find(t => t.id === id);
                    if (task) {
                        const filteredTasks = tasks.filter(t => t.id !== id);
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.TASKS, filteredTasks)) {
                            throw new Error('删除任务失败');
                        }
                        
                        this.addLog(id, task.name, `任务删除成功: ${task.name}`);
                        
                        // 同时删除关联的调度
                        this.deleteTaskSchedules(id);
                    }
                } catch (error) {
                    console.error('删除任务失败:', error);
                    throw error;
                }
            }

            // 删除关联的调度（内部方法）
            deleteTaskSchedules(taskId) {
                try {
                    const schedules = this.getSchedules();
                    const filteredSchedules = schedules.filter(s => s.taskId !== taskId);
                    if (schedules.length !== filteredSchedules.length) {
                        safeLocalStorageSet(STORAGE_KEYS.SCHEDULES, filteredSchedules);
                        this.addLog(taskId, '', `删除了${schedules.length - filteredSchedules.length}个关联的调度`);
                    }
                } catch (error) {
                    console.error('删除关联调度失败:', error);
                }
            }

            // 更新任务状态
            updateTaskStatus(id, enabled) {
                if (typeof id !== 'string' || typeof enabled !== 'boolean') {
                    throw new Error('参数无效');
                }

                try {
                    const tasks = this.getTasks();
                    const task = tasks.find(t => t.id === id);
                    if (task) {
                        task.enabled = enabled;
                        task.updatedAt = new Date().toISOString();
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.TASKS, tasks)) {
                            throw new Error('更新任务状态失败');
                        }
                        
                        this.addLog(id, task.name, `任务${enabled ? '启用' : '禁用'}成功: ${task.name}`);
                    }
                } catch (error) {
                    console.error('更新任务状态失败:', error);
                    throw error;
                }
            }
            
            // 更新任务部署状态
            updateTaskDeploymentStatus(id, deployed) {
                if (typeof id !== 'string' || typeof deployed !== 'boolean') {
                    throw new Error('参数无效');
                }

                try {
                    const tasks = this.getTasks();
                    const task = tasks.find(t => t.id === id);
                    if (task) {
                        task.deployed = deployed;
                        task.updatedAt = new Date().toISOString();
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.TASKS, tasks)) {
                            throw new Error('更新任务部署状态失败');
                        }
                        
                        this.addLog(id, task.name, `任务${deployed ? '上线' : '下线'}成功: ${task.name}`);
                    }
                } catch (error) {
                    console.error('更新任务部署状态失败:', error);
                    throw error;
                }
            }
            
            // 执行数据清洗任务
            executeTask(taskId) {
                try {
                    const task = this.getTasks().find(t => t.id === taskId);
                    if (!task) {
                        throw new Error('任务不存在');
                    }
                    
                    if (!task.enabled) {
                        throw new Error('任务已禁用');
                    }
                    
                    // 解析清洗规则
                    const rules = JSON.parse(task.rules);
                    
                    // 获取要处理的数据样本
                    const sampleData = this.getSampleData(taskId);
                    
                    // 执行数据清洗
                    const result = this.processDataWithRules(sampleData, rules);
                    
                    // 保存清洗结果
                    this.saveProcessingResult(taskId, result);
                    
                    // 记录日志
                    const logMessage = `数据清洗完成: 处理了 ${result.totalRecords} 条记录，修复了 ${result.fixedRecords} 条记录`;
                    this.addLog(taskId, task.name, logMessage, 'success');
                    
                    return result;
                } catch (error) {
                    console.error('执行数据清洗任务失败:', error);
                    throw error;
                }
            }
            
            // 获取样本数据
            getSampleData(taskId) {
                // 这里应该从实际数据源获取数据
                // 现在使用模拟数据
                const task = this.getTasks().find(t => t.id === taskId);
                if (!task) return [];
                
                // 根据任务类型生成不同的模拟数据
                if (task.name.includes('空值')) {
                    return [
                        { id: '1', ip: '192.168.1.1', timestamp: '2024-01-01T12:00:00Z', data: 'valid' },
                        { id: '2', ip: null, timestamp: '2024-01-01T12:01:00Z', data: 'valid' },
                        { id: '3', ip: '192.168.1.3', timestamp: null, data: 'valid' },
                        { id: '4', ip: '192.168.1.4', timestamp: '2024-01-01T12:03:00Z', data: null }
                    ];
                } else if (task.name.includes('IP')) {
                    return [
                        { id: '1', ip: '192.168.1.1', timestamp: '2024-01-01T12:00:00Z' },
                        { id: '2', ip: '999.999.999.999', timestamp: '2024-01-01T12:01:00Z' },
                        { id: '3', ip: '192.168.1.256', timestamp: '2024-01-01T12:02:00Z' },
                        { id: '4', ip: '10.0.0.1', timestamp: '2024-01-01T12:03:00Z' }
                    ];
                } else if (task.name.includes('时间戳')) {
                    return [
                        { id: '1', data: 'test', timestamp: '2024-01-01T12:00:00Z' },
                        { id: '2', data: 'test', timestamp: '2024/01/01 12:00:00' },
                        { id: '3', data: 'test', timestamp: '01-01-2024 12:00:00' },
                        { id: '4', data: 'test', timestamp: '2024-01-01' }
                    ];
                } else if (task.name.includes('敏感')) {
                    return [
                        { id: '1', name: '张三', idCard: '110101199001011234', phone: '13800138000' },
                        { id: '2', name: '李四', idCard: '310101199001015678', phone: '13900139000' }
                    ];
                } else if (task.name.includes('漏洞')) {
                    return [
                        { id: '1', cve: 'CVE-2024-1234', severity: 'high', description: '测试漏洞1', patchAvailable: true },
                        { id: '2', cve: 'cve_2024_5678', severity: 'MEDIUM', description: '测试漏洞2', patchAvailable: false },
                        { id: '3', cve: '2024-9999', severity: 'low', description: '测试漏洞3', patchAvailable: true }
                    ];
                } else {
                    // 默认数据
                    return [
                        { id: '1', field1: 'value1', field2: 'value2' },
                        { id: '2', field1: null, field2: 'value2' },
                        { id: '3', field1: 'value3', field2: '' }
                    ];
                }
            }
            
            // 根据规则处理数据
            processDataWithRules(data, rules) {
                let fixedRecords = 0;
                let processedData = [];
                
                // 确保rules是数组
                const validRules = Array.isArray(rules) ? rules : [];
                
                data.forEach((record, index) => {
                    let modified = false;
                    let recordCopy = { ...record };
                    
                    // 应用每条规则
                    validRules.forEach(rule => {
                        switch (rule.type) {
                            case 'null_check':
                                // 检查空值并修复
                                if (rule.fields && Array.isArray(rule.fields)) {
                                    rule.fields.forEach(field => {
                                        if (recordCopy[field] === null || recordCopy[field] === undefined || recordCopy[field] === '') {
                                            recordCopy[field] = rule.replaceWith || 'N/A';
                                            modified = true;
                                        }
                                    });
                                }
                                break;
                                
                            case 'ip_validation':
                                // IP地址验证和修复
                                if (recordCopy[rule.field]) {
                                    const isValidIp = this.validateIp(recordCopy[rule.field]);
                                    if (!isValidIp) {
                                        if (rule.replaceWith) {
                                            recordCopy[rule.field] = rule.replaceWith;
                                            modified = true;
                                        }
                                    }
                                }
                                break;
                                
                            case 'timestamp_normalization':
                                // 时间戳标准化
                                if (recordCopy[rule.field]) {
                                    const normalizedTime = this.normalizeTimestamp(recordCopy[rule.field]);
                                    if (normalizedTime !== recordCopy[rule.field]) {
                                        recordCopy[rule.field] = normalizedTime;
                                        modified = true;
                                    }
                                }
                                break;
                                
                            case 'data_masking':
                                // 数据脱敏
                                if (recordCopy[rule.field]) {
                                    const maskedValue = this.maskData(recordCopy[rule.field], rule.maskType);
                                    if (maskedValue !== recordCopy[rule.field]) {
                                        recordCopy[rule.field] = maskedValue;
                                        modified = true;
                                    }
                                }
                                break;
                                
                            case 'format_conversion':
                                // 格式转换
                                if (recordCopy[rule.field]) {
                                    const convertedValue = this.convertFormat(recordCopy[rule.field], rule.targetFormat);
                                    if (convertedValue !== recordCopy[rule.field]) {
                                        recordCopy[rule.field] = convertedValue;
                                        modified = true;
                                    }
                                }
                                break;
                        }
                    });
                    
                    if (modified) {
                        fixedRecords++;
                    }
                    processedData.push(recordCopy);
                });
                
                return {
                    originalData: data,
                    processedData: processedData,
                    totalRecords: data.length,
                    fixedRecords: fixedRecords
                };
            }
            
            // 验证IP地址
            validateIp(ip) {
                const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
                return ipRegex.test(ip);
            }
            
            // 标准化时间戳
            normalizeTimestamp(timestamp) {
                try {
                    const date = new Date(timestamp);
                    if (!isNaN(date.getTime())) {
                        return date.toISOString();
                    }
                } catch (e) {
                    console.error('时间戳标准化失败:', e);
                }
                return timestamp;
            }
            
            // 数据脱敏
            maskData(value, maskType) {
                switch (maskType) {
                    case 'idCard':
                        // 身份证脱敏：显示前6位和后4位
                        return value.replace(/^(\d{6})\d{8}(\d{4})$/i, '$1********$2');
                    case 'phone':
                        // 手机号脱敏：显示前3位和后4位
                        return value.replace(/^(\d{3})\d{4}(\d{4})$/i, '$1****$2');
                    case 'name':
                        // 姓名脱敏：只显示姓氏
                        if (value.length > 1) {
                            return value.charAt(0) + '*'.repeat(value.length - 1);
                        }
                        return value;
                    default:
                        return value;
                }
            }
            
            // 格式转换
            convertFormat(value, targetFormat) {
                switch (targetFormat) {
                    case 'uppercase':
                        return typeof value === 'string' ? value.toUpperCase() : value;
                    case 'lowercase':
                        return typeof value === 'string' ? value.toLowerCase() : value;
                    case 'cve_standard':
                        // CVE格式标准化
                        if (typeof value === 'string') {
                            return value.replace(/^cve[-_]?(\d{4})[-_]?(\d+)$/i, 'CVE-$1-$2').toUpperCase();
                        }
                        return value;
                    default:
                        return value;
                }
            }
            
            // 保存处理结果
            saveProcessingResult(taskId, result) {
                try {
                    const results = safeLocalStorageGet(STORAGE_KEYS.PROCESSING_RESULTS) || {};
                    results[taskId] = {
                        timestamp: new Date().toISOString(),
                        result: result
                    };
                    safeLocalStorageSet(STORAGE_KEYS.PROCESSING_RESULTS, results);
                } catch (error) {
                    console.error('保存处理结果失败:', error);
                }
            }

            // 获取所有调度
            getSchedules() {
                const data = safeLocalStorageGet(STORAGE_KEYS.SCHEDULES);
                if (!Array.isArray(data)) {
                    return [];
                }
                // 验证并过滤有效调度数据
                return data.filter(schedule => validateSchedule(schedule));
            }

            // 保存调度
            saveSchedule(schedule) {
                if (!validateSchedule(schedule)) {
                    console.error('调度数据格式无效:', schedule);
                    throw new Error('调度数据格式无效');
                }

                try {
                    const schedules = this.getSchedules();
                    const index = schedules.findIndex(s => s.id === schedule.id);
                    
                    schedule.updatedAt = new Date().toISOString();
                    
                    if (index >= 0) {
                        schedules[index] = schedule;
                    } else {
                        schedule.createdAt = new Date().toISOString();
                        schedules.push(schedule);
                    }
                    
                    if (!safeLocalStorageSet(STORAGE_KEYS.SCHEDULES, schedules)) {
                        throw new Error('保存调度失败');
                    }
                    
                    const task = this.getTasks().find(t => t.id === schedule.taskId);
                    this.addLog(schedule.taskId || '', task?.name || '', `调度${index >= 0 ? '更新' : '创建'}成功: ${schedule.name}`);
                } catch (error) {
                    console.error('保存调度失败:', error);
                    throw error;
                }
            }

            // 删除调度
            deleteSchedule(id) {
                if (typeof id !== 'string') {
                    throw new Error('调度ID无效');
                }

                try {
                    const schedules = this.getSchedules();
                    const schedule = schedules.find(s => s.id === id);
                    if (schedule) {
                        const filteredSchedules = schedules.filter(s => s.id !== id);
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.SCHEDULES, filteredSchedules)) {
                            throw new Error('删除调度失败');
                        }
                        
                        const task = this.getTasks().find(t => t.id === schedule.taskId);
                        this.addLog(schedule.taskId, task?.name || '', `调度删除成功: ${schedule.name}`);
                    }
                } catch (error) {
                    console.error('删除调度失败:', error);
                    throw error;
                }
            }

            // 更新调度状态
            updateScheduleStatus(id, enabled) {
                if (typeof id !== 'string' || typeof enabled !== 'boolean') {
                    throw new Error('参数无效');
                }

                try {
                    const schedules = this.getSchedules();
                    const schedule = schedules.find(s => s.id === id);
                    if (schedule) {
                        schedule.enabled = enabled;
                        schedule.updatedAt = new Date().toISOString();
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.SCHEDULES, schedules)) {
                            throw new Error('更新调度状态失败');
                        }
                        
                        const task = this.getTasks().find(t => t.id === schedule.taskId);
                        this.addLog(schedule.taskId, task?.name || '', `调度${enabled ? '启用' : '禁用'}成功: ${schedule.name}`);
                    }
                } catch (error) {
                    console.error('更新调度状态失败:', error);
                    throw error;
                }
            }

            // 更新调度的最后执行时间
            updateScheduleLastExecution(id) {
                if (typeof id !== 'string') {
                    throw new Error('调度ID无效');
                }

                try {
                    const schedules = this.getSchedules();
                    const schedule = schedules.find(s => s.id === id);
                    if (schedule) {
                        schedule.lastExecutionTime = new Date().toISOString();
                        schedule.updatedAt = new Date().toISOString();
                        
                        if (!safeLocalStorageSet(STORAGE_KEYS.SCHEDULES, schedules)) {
                            throw new Error('更新调度执行时间失败');
                        }
                    }
                } catch (error) {
                    console.error('更新调度执行时间失败:', error);
                    throw error;
                }
            }

            // 添加日志
            addLog(taskId, taskName, message, level = 'info') {
                try {
                    const logs = this.getLogs();
                    const log = {
                        id: Date.now().toString() + Math.random().toString(36).substr(2, 9), // 避免ID冲突
                        taskId,
                        taskName,
                        timestamp: new Date().toISOString(),
                        message,
                        level
                    };
                    
                    // 限制日志数量，保留最新的1000条
                    logs.unshift(log);
                    if (logs.length > 1000) {
                        logs.splice(1000);
                    }
                    
                    safeLocalStorageSet(STORAGE_KEYS.LOGS, logs);
                } catch (error) {
                    console.error('添加日志失败:', error);
                    // 日志添加失败不抛出异常，避免影响主流程
                }
            }

            // 获取日志
            getLogs() {
                const data = safeLocalStorageGet(STORAGE_KEYS.LOGS);
                if (!Array.isArray(data)) {
                    return [];
                }
                // 验证并过滤有效日志数据
                return data.filter(log => 
                    log &&
                    typeof log.id === 'string' &&
                    typeof log.taskId === 'string' &&
                    typeof log.taskName === 'string' &&
                    typeof log.timestamp === 'string' &&
                    typeof log.message === 'string' &&
                    ['info', 'warning', 'error', 'success'].includes(log.level)
                );
            }
            
            // 清空所有数据（用于调试）
            clearAllData() {
                try {
                    Object.values(STORAGE_KEYS).forEach(key => {
                        localStorage.removeItem(key);
                    });
                    this.addLog('', '', '所有数据已清空', 'warning');
                } catch (error) {
                    console.error('清空数据失败:', error);
                }
            }
        }

        // 创建数据存储实例
        const dataStorage = new DataStorage();
        
        // 规则构建器相关功能
        function initRuleBuilder() {
            // 选项卡切换
            document.querySelectorAll('.rule-tab').forEach(tab => {
                tab.addEventListener('click', function() {
                    const target = this.dataset.tab;
                    
                    // 更新选项卡样式
                    document.querySelectorAll('.rule-tab').forEach(t => {
                        t.classList.remove('active');
                        t.classList.add('text-text-secondary');
                    });
                    this.classList.add('active');
                    this.classList.remove('text-text-secondary');
                    
                    // 显示对应面板
                    document.getElementById('rule-builder-panel').classList.toggle('hidden', target !== 'builder');
                    document.getElementById('rule-json-panel').classList.toggle('hidden', target !== 'json');
                    
                    // 从构建器同步到JSON
                    if (target === 'json') {
                        syncRulesToJson();
                    }
                });
            });
            
            // 添加规则按钮事件
            document.querySelectorAll('.add-rule-btn').forEach(btn => {
                btn.addEventListener('click', function() {
                    const ruleType = this.dataset.ruleType;
                    addRule(ruleType);
                });
            });
            
            // 格式化JSON按钮
            document.getElementById('format-json-btn')?.addEventListener('click', formatJson);
            
            // 任务表单提交前同步规则
            document.getElementById('task-form')?.addEventListener('submit', syncRulesToJson);
        }

        // 规则类型配置映射
        const ruleTypeConfigs = {
            null_check: {
                name: '空值检查',
                icon: 'fa-ban',
                fields: [
                    { name: 'field', label: '字段', type: 'text', placeholder: '* 或具体字段名', default: '*' },
                    { name: 'action', label: '处理方式', type: 'select', options: ['remove', 'set_default', 'flag'], default: 'remove' },
                    { name: 'default_value', label: '默认值', type: 'text', condition: 'action === "set_default"' }
                ]
            },
            ip_validation: {
                name: 'IP验证',
                icon: 'fa-globe',
                fields: [
                    { name: 'field', label: 'IP字段', type: 'text', placeholder: '如：ip_address', default: 'ip_address' },
                    { name: 'version', label: 'IP版本', type: 'select', options: ['all', 'ipv4', 'ipv6'], default: 'all' },
                    { name: 'action', label: '验证失败处理', type: 'select', options: ['remove', 'flag', 'set_null'], default: 'flag' }
                ]
            },
            timestamp_normalization: {
                name: '时间标准化',
                icon: 'fa-clock-o',
                fields: [
                    { name: 'field', label: '时间字段', type: 'text', placeholder: '如：created_at', default: 'created_at' },
                    { name: 'format', label: '输出格式', type: 'text', placeholder: 'YYYY-MM-DD HH:mm:ss', default: 'YYYY-MM-DD HH:mm:ss' },
                    { name: 'action', label: '无效时间处理', type: 'select', options: ['remove', 'set_null', 'flag'], default: 'flag' }
                ]
            },
            data_masking: {
                name: '数据脱敏',
                icon: 'fa-eye-slash',
                fields: [
                    { name: 'field', label: '需要脱敏的字段', type: 'text', placeholder: '如：phone,email', default: 'phone' },
                    { name: 'mask_type', label: '脱敏类型', type: 'select', options: ['partial', 'full', 'hash'], default: 'partial' },
                    { name: 'mask_char', label: '掩码字符', type: 'text', placeholder: '*', default: '*' }
                ]
            },
            format_conversion: {
                name: '格式转换',
                icon: 'fa-exchange',
                fields: [
                    { name: 'field', label: '需要转换的字段', type: 'text', placeholder: '如：amount', default: 'amount' },
                    { name: 'to_type', label: '目标类型', type: 'select', options: ['number', 'string', 'boolean', 'date'], default: 'number' },
                    { name: 'action', label: '转换失败处理', type: 'select', options: ['remove', 'set_null', 'flag'], default: 'flag' }
                ]
            }
        };

        // 添加规则
        function addRule(ruleType) {
            const config = ruleTypeConfigs[ruleType];
            if (!config) return;
            
            const rulesList = document.getElementById('rules-list');
            const emptyState = rulesList.querySelector('.text-center');
            if (emptyState) {
                rulesList.removeChild(emptyState);
            }
            
            const ruleId = Date.now();
            const ruleElement = document.createElement('div');
            ruleElement.className = 'rule-item p-4 rounded-lg transition-all duration-200 hover:shadow-md hover:translate-y-[-2px]';
            ruleElement.dataset.ruleId = ruleId;
            ruleElement.dataset.ruleType = ruleType;
            
            // 创建规则标题
            const ruleHeader = document.createElement('div');
            ruleHeader.className = 'flex justify-between items-center mb-3 pb-2 border-b border-border/50';
            ruleHeader.innerHTML = `
                <span class="font-medium text-sm text-text-primary flex items-center">
                    <i class="fa ${config.icon} mr-2 text-primary"></i>${config.name}
                </span>
                <div class="flex space-x-2">
                    <button type="button" class="rule-action-btn edit p-1.5 rounded-md hover:bg-gray-100 transition-colors" title="编辑规则">
                        <i class="fa fa-pencil text-text-secondary hover:text-primary"></i>
                    </button>
                    <button type="button" class="rule-action-btn delete p-1.5 rounded-md hover:bg-gray-100 transition-colors" title="删除规则">
                        <i class="fa fa-trash text-text-secondary hover:text-red-500"></i>
                    </button>
                </div>
            `;
            
            // 创建规则配置表单
            const ruleForm = document.createElement('div');
            ruleForm.className = 'rule-config space-y-4';
            
            // 创建默认规则对象
            config.fields.forEach(field => {
                const fieldContainer = document.createElement('div');
                fieldContainer.className = 'flex flex-col';
                fieldContainer.innerHTML = `
                    <label class="text-xs font-medium text-text-secondary mb-1.5">${field.label}</label>
                    ${field.type === 'select' ? 
                        `<select class="rule-field form-input w-full px-3 py-2 rounded-md text-sm focus:ring-2 focus:ring-primary/50 transition-all" data-field="${field.name}">
                            ${field.options.map(option => 
                                `<option value="${option}" ${option === field.default ? 'selected' : ''}>${option}</option>`
                            ).join('')}
                        </select>` : 
                        `<input type="${field.type}" class="rule-field form-input w-full px-3 py-2 rounded-md text-sm focus:ring-2 focus:ring-primary/50 transition-all" data-field="${field.name}" placeholder="${field.placeholder}" value="${field.default}">
                    `}
                `;
                ruleForm.appendChild(fieldContainer);
            });
            
            ruleElement.appendChild(ruleHeader);
            ruleElement.appendChild(ruleForm);
            rulesList.appendChild(ruleElement);
            
            // 添加事件监听
            ruleElement.querySelector('.delete-rule-btn, .rule-action-btn.delete').addEventListener('click', () => deleteRule(ruleId));
            
            // 添加字段值变化事件，以处理条件显示逻辑
            ruleElement.querySelectorAll('.rule-field').forEach(field => {
                field.addEventListener('change', updateRuleConditions);
                field.addEventListener('input', updateRuleConditions);
            });
            
            // 初始化条件显示
            updateRuleConditions();
        }

        // 更新规则条件显示
        function updateRuleConditions() {
            const rulesList = document.getElementById('rules-list');
            
            rulesList.querySelectorAll('.rule-item').forEach(ruleItem => {
                const ruleType = ruleItem.dataset.ruleType;
                const config = ruleTypeConfigs[ruleType];
                if (!config) return;
                
                config.fields.forEach(field => {
                    if (field.condition) {
                        const fieldElement = ruleItem.querySelector(`[data-field="${field.name}"]`);
                        if (fieldElement) {
                            // 评估条件
                            const ruleData = getRuleData(ruleItem);
                            let conditionMet = false;
                            try {
                                conditionMet = eval(`(function() { return ${field.condition} })()`);
                            } catch (e) {
                                console.error('条件评估错误:', e);
                            }
                            
                            // 显示或隐藏字段容器
                            const fieldContainer = fieldElement.closest('div[class*="flex-col"]');
                            if (fieldContainer) {
                                fieldContainer.classList.toggle('hidden', !conditionMet);
                            }
                        }
                    }
                });
            });
        }

        // 获取规则数据
        function getRuleData(ruleItem) {
            const ruleData = { type: ruleItem.dataset.ruleType || '' };
            
            ruleItem.querySelectorAll('.rule-field').forEach(field => {
                const fieldName = field.dataset.field;
                ruleData[fieldName] = field.value;
            });
            
            return ruleData;
        }

        // 删除规则
        function deleteRule(ruleId) {
            const ruleItem = document.querySelector(`.rule-item[data-rule-id="${ruleId}"]`);
            if (ruleItem) {
                ruleItem.remove();
            }
            
            // 检查是否需要显示空状态
            const rulesList = document.getElementById('rules-list');
            if (rulesList.querySelectorAll('.rule-item').length === 0) {
                rulesList.innerHTML = `
                    <div class="text-center text-text-secondary text-sm py-6">
                        <i class="fa fa-list-ul text-2xl mb-2 opacity-50 float-animation"></i>
                        <p>暂无规则，请添加规则</p>
                    </div>
                `;
            }
        }

        // 同步规则到JSON
        function syncRulesToJson() {
            const rulesList = document.getElementById('rules-list');
            const ruleItems = rulesList.querySelectorAll('.rule-item');
            const rules = [];
            
            ruleItems.forEach(item => {
                const ruleData = getRuleData(item);
                rules.push(ruleData);
            });
            
            const rulesJson = { rules };
            const textarea = document.getElementById('task-rules');
            if (textarea) {
                textarea.value = JSON.stringify(rulesJson, null, 2);
            }
        }

        // 从JSON同步到规则构建器
        function syncJsonToRules(jsonStr) {
            try {
                const rulesJson = JSON.parse(jsonStr);
                const rules = rulesJson.rules || [];
                
                // 清空现有规则
                const rulesList = document.getElementById('rules-list');
                rulesList.innerHTML = '';
                
                // 添加规则
                rules.forEach(rule => {
                    const ruleType = rule.type;
                    if (ruleTypeConfigs[ruleType]) {
                        // 添加规则
                        addRule(ruleType);
                        
                        // 填充规则数据
                        const lastRule = rulesList.lastElementChild;
                        Object.keys(rule).forEach(key => {
                            const field = lastRule.querySelector(`[data-field="${key}"]`);
                            if (field) {
                                field.value = rule[key];
                            }
                        });
                    }
                });
                
                // 如果没有规则，显示空状态
                if (rules.length === 0) {
                    rulesList.innerHTML = `
                        <div class="text-center text-text-secondary text-sm py-4">
                            暂无规则，请添加规则
                        </div>
                    `;
                }
                
                // 更新条件显示
                updateRuleConditions();
            } catch (e) {
                showNotification('JSON格式错误，请检查', 'error');
            }
        }

        // 格式化JSON
        function formatJson() {
            const textarea = document.getElementById('task-rules');
            try {
                const parsed = JSON.parse(textarea.value);
                textarea.value = JSON.stringify(parsed, null, 2);
            } catch (e) {
                showNotification('JSON格式错误，无法格式化', 'error');
            }
        }

        // 初始化示例数据
        function initializeSampleData() {
            const tasks = dataStorage.getTasks();
            if (tasks.length === 0) {
                // 添加示例任务 - 增强版，专注于安全数据清洗
                const sampleTasks = [
                    {
                        id: '1',
                        name: '安全数据空值检测与修复',
                        description: '检测并处理安全数据中的空值和缺失字段',
                        rules: '{"rules":[{"type":"detect_empty","field":"*","action":"flag"},{"type":"fill_empty","field":"ip_address","value":"unknown"},{"type":"default_values","field":"severity","value":"medium"},{"type":"remove_empty","field":"timestamp"}]}',
                        enabled: true,
                        deployed: true,
                        createdAt: new Date().toISOString(),
                        updatedAt: new Date().toISOString()
                    },
                    {
                        id: '2',
                        name: 'IP地址格式验证与修正',
                        description: '验证IP地址格式，修正常见错误格式',
                        rules: '{"rules":[{"type":"validate_format","field":"source_ip","pattern":"ip","action":"correct"},{"type":"validate_format","field":"destination_ip","pattern":"ip","action":"correct"},{"type":"flag_invalid","field":"source_ip","pattern":"ip"}]}',
                        enabled: true,
                        deployed: true,
                        createdAt: new Date(Date.now() - 86400000).toISOString(), // 昨天
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '3',
                        name: '安全事件数据去重与合并',
                        description: '基于事件ID和时间戳去除重复的安全事件',
                        rules: '{"rules":[{"type":"deduplicate","field":"event_id"},{"type":"merge_records","field":"session_id","strategy":"latest"}]}',
                        enabled: true,
                        deployed: false,
                        createdAt: new Date(Date.now() - 172800000).toISOString(), // 前天
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '4',
                        name: '时间戳标准化与时区转换',
                        description: '统一时间戳格式，处理时区差异',
                        rules: '{"rules":[{"type":"format_date","field":"event_time","format":"ISO8601"},{"type":"timezone_convert","field":"event_time","from":"UTC","to":"Asia/Shanghai"}]}',
                        enabled: false,
                        deployed: false,
                        createdAt: new Date(Date.now() - 259200000).toISOString(), // 3天前
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '5',
                        name: '敏感数据脱敏处理',
                        description: '对个人身份信息等敏感数据进行脱敏处理',
                        rules: '{"rules":[{"type":"mask","field":"email","pattern":"***@***"},{"type":"mask","field":"phone","pattern":"****"},{"type":"hash","field":"user_id","algorithm":"md5"},{"type":"remove","field":"password_hash"}]}',
                        enabled: true,
                        deployed: true,
                        createdAt: new Date(Date.now() - 345600000).toISOString(), // 4天前
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '6',
                        name: '安全漏洞数据格式标准化',
                        description: '统一不同来源的漏洞数据格式，填充缺失信息',
                        rules: '{"rules":[{"type":"map_values","field":"severity","mapping":{"Critical":"high","Major":"high","Minor":"medium"}},{"type":"validate_format","field":"cve_id","pattern":"CVE-\\d{4}-\\d{4,7}","action":"flag"},{"type":"format_text","field":"description","trim":true}]}',
                        enabled: true,
                        deployed: true,
                        createdAt: new Date(Date.now() - 432000000).toISOString(), // 5天前
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '7',
                        name: '用户行为数据清洗',
                        description: '清洗和标准化用户行为日志数据',
                        rules: '{"rules":[{"type":"validate_format","field":"user_id","pattern":"uuid","action":"flag"},{"type":"remove_duplicates","field":"event_id"},{"type":"category_mapping","field":"action","mapping":{"click":"interaction","hover":"interaction","submit":"action"}}]}',
                        enabled: true,
                        deployed: false,
                        createdAt: new Date(Date.now() - 518400000).toISOString(), // 6天前
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    },
                    {
                        id: '8',
                        name: '网络流量数据过滤',
                        description: '过滤和清洗网络流量数据',
                        rules: '{"rules":[{"type":"ip_filter","field":"source_ip","allowed_ranges":["192.168.0.0/16","10.0.0.0/8"]},{"type":"port_validation","field":"destination_port","allowed_ports":[80,443,22]},{"type":"protocol_validation","field":"protocol","allowed_protocols":["TCP","UDP"]}]}',
                        enabled: true,
                        deployed: true,
                        createdAt: new Date(Date.now() - 604800000).toISOString(), // 7天前
                        updatedAt: new Date(Date.now() - 86400000).toISOString()
                    }
                ];

                sampleTasks.forEach(task => dataStorage.saveTask(task));

                // 添加示例调度
                const sampleSchedules = [
                    {
                        id: '1',
                        name: '每小时安全数据空值检测',
                        taskId: '1',
                        type: 'cron',
                        expression: '0 * * * * ?', // 每小时执行
                        enabled: true,
                        createdAt: new Date().toISOString(),
                        updatedAt: new Date().toISOString(),
                        lastExecutionTime: new Date(Date.now() - 3600000).toISOString() // 1小时前
                    },
                    {
                        id: '2',
                        name: '每日IP地址格式验证',
                        taskId: '2',
                        type: 'cron',
                        expression: '0 0 1 * * ?', // 每天凌晨1点执行
                        enabled: true,
                        createdAt: new Date(Date.now() - 86400000).toISOString(),
                        updatedAt: new Date(Date.now() - 86400000).toISOString(),
                        lastExecutionTime: new Date(Date.now() - 43200000).toISOString() // 12小时前
                    },
                    {
                        id: '3',
                        name: '实时去重检查',
                        taskId: '3',
                        type: 'interval',
                        expression: '1800', // 每30分钟执行一次
                        enabled: true,
                        createdAt: new Date(Date.now() - 172800000).toISOString(),
                        updatedAt: new Date(Date.now() - 86400000).toISOString(),
                        lastExecutionTime: new Date(Date.now() - 1800000).toISOString() // 30分钟前
                    },
                    {
                        id: '4',
                        name: '每周敏感数据脱敏',
                        taskId: '5',
                        type: 'cron',
                        expression: '0 0 2 ? * SUN', // 每周日凌晨2点执行
                        enabled: true,
                        createdAt: new Date(Date.now() - 259200000).toISOString(),
                        updatedAt: new Date(Date.now() - 86400000).toISOString(),
                        lastExecutionTime: new Date(Date.now() - 604800000).toISOString() // 1周前
                    },
                    {
                        id: '5',
                        name: '每6小时漏洞数据更新',
                        taskId: '6',
                        type: 'cron',
                        expression: '0 0 */6 * * ?', // 每6小时执行
                        enabled: true,
                        createdAt: new Date(Date.now() - 345600000).toISOString(),
                        updatedAt: new Date(Date.now() - 86400000).toISOString(),
                        lastExecutionTime: new Date(Date.now() - 21600000).toISOString() // 6小时前
                    }
                ];

                sampleSchedules.forEach(schedule => dataStorage.saveSchedule(schedule));

                // 添加详细的示例日志
                const now = new Date();
                
                // 今天的日志 - 更丰富的内容
                dataStorage.addLog('1', '安全数据空值检测与修复', '任务执行成功，处理了10000条记录，发现并修复了124条空值记录，标记了35条无法自动修复的异常记录', 'success');
                dataStorage.addLog('2', 'IP地址格式验证与修正', '发现56条格式异常的IP地址，成功修正48条，8条无法修复已标记', 'warning');
                dataStorage.addLog('3', '安全事件数据去重与合并', '成功识别并合并了23条重复事件记录，提高了数据质量', 'success');
                dataStorage.addLog('5', '敏感数据脱敏处理', '完成对5000条用户记录的脱敏处理，保护了个人隐私信息', 'success');
                
                // 昨天的日志
                dataStorage.addLog('1', '安全数据空值检测与修复', '定时任务执行完成，耗时27秒，清理了85条空值记录', 'info');
                dataStorage.addLog('3', '安全事件数据去重与合并', '本次执行未发现重复记录', 'info');
                dataStorage.addLog('6', '安全漏洞数据格式标准化', '成功标准化了320条漏洞记录，统一了严重级别分类', 'info');
                
                // 前天的日志
                dataStorage.addLog('2', 'IP地址格式验证与修正', '发现并修正了12条IPv4地址格式错误，所有数据现在符合RFC标准', 'info');
                dataStorage.addLog('4', '时间戳标准化与时区转换', '任务当前处于禁用状态，等待配置更新', 'warning');
                dataStorage.addLog('6', '安全漏洞数据格式标准化', '执行过程中遇到异常：无法解析的CVSS评分格式，已跳过相关记录', 'error');
                dataStorage.addLog('5', '敏感数据脱敏处理', '处理到第1234条记录时发现异常格式，已自动跳过并记录', 'warning');
                
                // 3天前的日志
                dataStorage.addLog('1', '安全数据空值检测与修复', '检测到大量空值记录，建议检查数据源完整性', 'warning');
                dataStorage.addLog('3', '安全事件数据去重与合并', '合并算法优化后执行效率提升40%', 'info');
                dataStorage.addLog('0', '系统', '数据清洗模块已自动备份所有配置', 'info');
            }
        }

        // 初始化标签页
        function initTabs() {
            const tabs = document.querySelectorAll('.nav-tab');
            tabs.forEach(tab => {
                tab.addEventListener('click', () => {
                    // 移除所有标签的激活状态
                    tabs.forEach(t => {
                        t.classList.remove('text-primary', 'border-b-2', 'border-primary', '-mb-[1px]', 'rounded-t-md');
                        t.classList.add('text-text-secondary');
                    });

                    // 添加当前标签的激活状态
                    tab.classList.remove('text-text-secondary');
                    tab.classList.add('text-primary', 'border-b-2', 'border-primary', '-mb-[1px]', 'rounded-t-md');

                    // 隐藏所有面板
                    const panels = document.querySelectorAll('.tab-panel');
                    panels.forEach(panel => panel.classList.add('hidden'));

                    // 显示当前面板
                    const target = tab.getAttribute('data-target');
                    if (target) {
                        const currentPanel = document.getElementById(target);
                        if (currentPanel) {
                            currentPanel.classList.remove('hidden');
                            
                            // 如果是日志面板，刷新日志数据
                            if (target === 'logs-panel') {
                                loadLogTaskOptions();
                                loadLogs();
                            }
                        }
                    }
                });
            });
        }

        // 初始化任务管理
        function initTaskManagement() {
            // 加载任务列表
            loadTasks();

            // 添加任务按钮点击事件
            document.getElementById('add-task-btn')?.addEventListener('click', () => {
                openTaskModal();
            });

            // 关闭任务模态框
            document.getElementById('close-task-modal')?.addEventListener('click', closeTaskModal);
            document.getElementById('cancel-task-btn')?.addEventListener('click', closeTaskModal);

            // 保存任务
            document.getElementById('save-task-btn')?.addEventListener('click', saveTask);

            // 搜索和过滤事件
            document.getElementById('task-search')?.addEventListener('input', loadTasks);
            document.getElementById('task-status-filter')?.addEventListener('change', loadTasks);
        }

        // 加载任务列表
        function loadTasks() {
            const tasks = dataStorage.getTasks();
            const searchInput = document.getElementById('task-search').value.toLowerCase();
            const statusFilter = document.getElementById('task-status-filter').value;

            // 过滤任务
            let filteredTasks = tasks.filter(task => 
                task.name.toLowerCase().includes(searchInput)
            );

            // 状态过滤
            if (statusFilter !== 'all') {
                filteredTasks = filteredTasks.filter(task => 
                    task.enabled === (statusFilter === 'enabled')
                );
            }

            // 按创建时间倒序排序
            filteredTasks.sort((a, b) => 
                new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
            );

            const tableBody = document.getElementById('tasks-table-body');
            const emptyState = document.getElementById('tasks-empty-state');

            if (tableBody && emptyState) {
                if (filteredTasks.length === 0) {
                    tableBody.innerHTML = '';
                    emptyState.classList.remove('hidden');
                } else {
                    emptyState.classList.add('hidden');
                    tableBody.innerHTML = '';

                    filteredTasks.forEach(task => {
                        const row = document.createElement('tr');
                        row.className = 'border-b border-gray-100 table-row-hover smooth-transition';

                        // 格式化日期
                        const formattedDate = new Date(task.createdAt).toLocaleString('zh-CN');

                        row.innerHTML = `
                            <td class="px-4 py-3">${task.name}</td>
                            <td class="px-4 py-3 text-text-secondary text-sm">${task.description || '-'}</td>
                            <td class="px-4 py-3">
                                <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${task.deployed ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}">
                                    ${task.deployed ? '已上线' : '未上线'}
                                </span>
                            </td>
                            <td class="px-4 py-3 text-text-secondary text-sm">${formattedDate}</td>
                            <td class="px-4 py-3">
                                <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${task.enabled ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}">
                                    ${task.enabled ? '已启用' : '已禁用'}
                                </span>
                            </td>
                            <td class="px-4 py-3">
                                <div class="flex space-x-2">
                                    <button class="text-primary hover:text-primary/80 transition-colors edit-task" data-id="${task.id}">
                                        <i class="fa fa-edit mr-1"></i>编辑
                                    </button>
                                    <button class="text-success hover:text-success/80 transition-colors run-task" data-id="${task.id}">
                                        <i class="fa fa-play-circle mr-1"></i>执行
                                    </button>
                                    <button class="text-text-secondary hover:text-dark transition-colors toggle-task" data-id="${task.id}" data-enabled="${task.enabled}">
                                        <i class="fa ${task.enabled ? 'fa-pause' : 'fa-play'} mr-1"></i>${task.enabled ? '禁用' : '启用'}
                                    </button>
                                    <button class="text-blue-500 hover:text-blue-600 transition-colors deploy-task" data-id="${task.id}" data-deployed="${task.deployed}">
                                        <i class="fa ${task.deployed ? 'fa-arrow-down' : 'fa-arrow-up'} mr-1"></i>${task.deployed ? '下线' : '上线'}
                                    </button>
                                    <button class="text-red-500 hover:text-red-600 transition-colors delete-task" data-id="${task.id}">
                                        <i class="fa fa-trash mr-1"></i>删除
                                    </button>
                                </div>
                            </td>
                        `;

                        tableBody.appendChild(row);
                    });

                    // 添加编辑事件
                    document.querySelectorAll('.edit-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                editTask(id);
                            }
                        });
                    });

                    // 添加启用/禁用事件
                    document.querySelectorAll('.toggle-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            const enabled = e.currentTarget.getAttribute('data-enabled') === 'true';
                            if (id) {
                                toggleTaskStatus(id, !enabled, e.currentTarget);
                            }
                        });
                    });

                    // 添加删除事件
                    document.querySelectorAll('.delete-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                deleteTask(id, e.currentTarget);
                            }
                        });
                    });
                    
                    // 添加执行事件
                    document.querySelectorAll('.run-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                runTask(id, e.currentTarget);
                            }
                        });
                    });
                    
                    // 添加部署事件
                    document.querySelectorAll('.deploy-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            const deployed = e.currentTarget.getAttribute('data-deployed') === 'true';
                            if (id) {
                                toggleTaskDeployment(id, !deployed, e.currentTarget);
                            }
                        });
                    });
                    
                    // 添加上线/下线事件
                    document.querySelectorAll('.deploy-task').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            const deployed = e.currentTarget.getAttribute('data-deployed') === 'true';
                            if (id) {
                                toggleTaskDeployment(id, !deployed);
                            }
                        });
                    });
                }
            }
        }

        // 打开任务编辑模态框
        function openTaskModal(task) {
            const modal = document.getElementById('task-modal');
            const modalTitle = document.getElementById('task-modal-title');
            const taskIdInput = document.getElementById('task-id');
            const taskNameInput = document.getElementById('task-name');
            const taskDescriptionInput = document.getElementById('task-description');
            const taskRulesInput = document.getElementById('task-rules');
            const taskEnabledCheckbox = document.getElementById('task-enabled');

            if (modal && modalTitle && taskIdInput && taskNameInput && taskDescriptionInput && taskRulesInput && taskEnabledCheckbox) {
                if (task) {
                    modalTitle.textContent = '编辑任务';
                    taskIdInput.value = task.id;
                    taskNameInput.value = task.name;
                    taskDescriptionInput.value = task.description;
                    taskRulesInput.value = task.rules;
                    taskEnabledCheckbox.checked = task.enabled;
                    
                    // 将JSON规则同步到规则构建器
                    if (task.rules) {
                        syncJsonToRules(task.rules);
                    }
                } else {
                    modalTitle.textContent = '添加任务';
                    taskIdInput.value = '';
                    taskNameInput.value = '';
                    taskDescriptionInput.value = '';
                    taskRulesInput.value = '{"rules":[]}';
                    taskEnabledCheckbox.checked = true;
                    
                    // 清空规则构建器
                    syncJsonToRules('{"rules":[]}');
                }

                modal.classList.remove('hidden');
                taskNameInput.focus();
            }
        }

        // 关闭任务编辑模态框
        function closeTaskModal() {
            const modal = document.getElementById('task-modal');
            if (modal) {
                modal.classList.add('hidden');
            }
        }

        // 编辑任务
        function editTask(id) {
            const tasks = dataStorage.getTasks();
            const task = tasks.find(t => t.id === id);
            if (task) {
                openTaskModal(task);
            }
        }

        // 保存任务
        function saveTask() {
            const saveBtn = document.getElementById('save-task-btn');
            const taskIdInput = document.getElementById('task-id');
            const taskNameInput = document.getElementById('task-name');
            const taskDescriptionInput = document.getElementById('task-description');
            const taskRulesInput = document.getElementById('task-rules');
            const taskEnabledCheckbox = document.getElementById('task-enabled');

            if (taskNameInput.value.trim() === '') {
                alert('请输入任务名称');
                taskNameInput.focus();
                return;
            }

            if (taskRulesInput.value.trim() === '') {
                alert('请输入清洗规则配置');
                taskRulesInput.focus();
                return;
            }

            // 验证JSON格式
            try {
                JSON.parse(taskRulesInput.value);
            } catch (e) {
                alert('清洗规则配置必须是有效的JSON格式');
                taskRulesInput.focus();
                return;
            }

            const task = {
                id: taskIdInput.value || Date.now().toString(),
                name: taskNameInput.value.trim(),
                description: taskDescriptionInput.value.trim(),
                rules: taskRulesInput.value.trim(),
                enabled: taskEnabledCheckbox.checked,
                createdAt: '', // 会在saveTask中设置
                updatedAt: ''  // 会在saveTask中设置
            };

            // 添加loading状态
            saveBtn.disabled = true;
            saveBtn.classList.add('btn-loading');

            // 添加2秒延迟模拟真实操作
            setTimeout(function() {
                dataStorage.saveTask(task);
                closeTaskModal();
                loadTasks();
                updateScheduleTaskOptions();
                
                // 移除loading状态
                saveBtn.disabled = false;
                saveBtn.classList.remove('btn-loading');
            }, 2000);
        }

        // 切换任务状态
        function toggleTaskStatus(id, enabled, button) {
            // 添加loading状态
            if (button) {
                button.classList.add('btn-loading');
                button.disabled = true;
            }
            
            // 添加2秒延迟模拟真实操作
            setTimeout(function() {
                dataStorage.updateTaskStatus(id, enabled);
                loadTasks();
                
                // 移除loading状态
                if (button) {
                    button.classList.remove('btn-loading');
                    button.disabled = false;
                }
            }, 2000);
        }
        
        // 切换任务部署状态（上线/下线）
        function toggleTaskDeployment(id, deployed, button) {
            // 添加loading状态
            if (button) {
                button.classList.add('btn-loading');
                button.disabled = true;
            }
            
            // 添加2秒延迟模拟真实操作
            setTimeout(function() {
                dataStorage.updateTaskDeploymentStatus(id, deployed);
                loadTasks();
                
                // 移除loading状态
                if (button) {
                    button.classList.remove('btn-loading');
                    button.disabled = false;
                }
            }, 2000);
        }

        // 删除任务
        function deleteTask(id, button) {
            if (confirm('确定要删除这个任务吗？删除后相关的调度也将失效。')) {
                // 添加loading状态
                if (button) {
                    button.classList.add('btn-loading');
                    button.disabled = true;
                }
                
                // 添加2秒延迟模拟真实操作
                setTimeout(function() {
                    dataStorage.deleteTask(id);
                    loadTasks();
                    updateScheduleTaskOptions();
                    loadSchedules();
                    
                    // 移除loading状态
                    if (button) {
                        button.classList.remove('btn-loading');
                        button.disabled = false;
                    }
                }, 2000);
            }
        }

        // 初始化任务调度
        function initTaskScheduling() {
            // 加载调度列表
            loadSchedules();

            // 更新任务选项
            updateScheduleTaskOptions();

            // 添加调度按钮点击事件
            document.getElementById('add-schedule-btn')?.addEventListener('click', () => {
                openScheduleModal();
            });

            // 关闭调度模态框
            document.getElementById('close-schedule-modal')?.addEventListener('click', closeScheduleModal);
            document.getElementById('cancel-schedule-btn')?.addEventListener('click', closeScheduleModal);

            // 保存调度
            document.getElementById('save-schedule-btn')?.addEventListener('click', saveSchedule);
        }

        // 更新调度任务选项
        function updateScheduleTaskOptions() {
            const tasks = dataStorage.getTasks();
            const taskSelect = document.getElementById('schedule-task');

            if (taskSelect) {
                // 保存当前选中的值
                const selectedValue = taskSelect.value;
                
                // 清空现有选项（保留第一个）
                const firstOption = taskSelect.firstElementChild;
                taskSelect.innerHTML = '';
                if (firstOption) {
                    taskSelect.appendChild(firstOption);
                }

                // 添加任务选项
                tasks.forEach(task => {
                    const option = document.createElement('option');
                    option.value = task.id;
                    option.textContent = task.name;
                    taskSelect.appendChild(option);
                });

                // 恢复选中值
                if (tasks.some(t => t.id === selectedValue)) {
                    taskSelect.value = selectedValue;
                }
            }
        }

        // 加载调度列表
        function loadSchedules() {
            const schedules = dataStorage.getSchedules();
            const tasks = dataStorage.getTasks();

            // 按创建时间倒序排序
            schedules.sort((a, b) => 
                new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
            );

            const tableBody = document.getElementById('schedules-table-body');
            const emptyState = document.getElementById('schedules-empty-state');

            if (tableBody && emptyState) {
                if (schedules.length === 0) {
                    tableBody.innerHTML = '';
                    emptyState.classList.remove('hidden');
                } else {
                    emptyState.classList.add('hidden');
                    tableBody.innerHTML = '';

                    schedules.forEach(schedule => {
                        const task = tasks.find(t => t.id === schedule.taskId);
                        const row = document.createElement('tr');
                        row.className = 'border-b border-gray-100 table-row-hover smooth-transition';

                        row.innerHTML = `
                            <td class="px-4 py-3">${schedule.name}</td>
                            <td class="px-4 py-3 text-text-secondary text-sm">${task?.name || '未知任务'}</td>
                            <td class="px-4 py-3">${schedule.type === 'cron' ? 'Cron表达式' : '固定间隔'}</td>
                            <td class="px-4 py-3 font-mono text-sm">${schedule.expression}</td>
                            <td class="px-4 py-3">
                                <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${schedule.enabled ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}">
                                    ${schedule.enabled ? '已启用' : '已禁用'}
                                </span>
                            </td>
                            <td class="px-4 py-3 text-text-secondary text-sm">${schedule.lastExecutionTime ? formatDateTime(new Date(schedule.lastExecutionTime)) : '-'}</td>
                            <td class="px-4 py-3 text-text-secondary text-sm">${schedule.nextExecutionTime ? formatDateTime(new Date(schedule.nextExecutionTime)) : '-'}</td>
                            <td class="px-4 py-3">
                                <div class="flex space-x-2">
                                    <button class="text-primary hover:text-primary/80 smooth-transition edit-schedule" data-id="${schedule.id}">
                                        <i class="fa fa-edit mr-1"></i>编辑
                                    </button>
                                    <button class="text-info hover:text-info/80 smooth-transition view-schedule" data-id="${schedule.id}">
                                        <i class="fa fa-eye mr-1"></i>详情
                                    </button>
                                    <button class="text-text-secondary hover:text-dark smooth-transition toggle-schedule" data-id="${schedule.id}" data-enabled="${schedule.enabled}">
                                        <i class="fa ${schedule.enabled ? 'fa-pause' : 'fa-play'} mr-1"></i>${schedule.enabled ? '禁用' : '启用'}
                                    </button>
                                    <button class="text-red-500 hover:text-red-600 smooth-transition delete-schedule" data-id="${schedule.id}">
                                        <i class="fa fa-trash mr-1"></i>删除
                                    </button>
                                    <button class="text-blue-500 hover:text-blue-600 smooth-transition execute-schedule" data-id="${schedule.id}">
                                        <i class="fa fa-play-circle mr-1"></i>执行
                                    </button>
                                </div>
                            </td>
                        `;

                        tableBody.appendChild(row);
                    });

                    // 添加编辑事件
                    document.querySelectorAll('.edit-schedule').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                editSchedule(id);
                            }
                        });
                    });

                    // 添加启用/禁用事件
                    document.querySelectorAll('.toggle-schedule').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            const enabled = e.currentTarget.getAttribute('data-enabled') === 'true';
                            if (id) {
                                toggleScheduleStatus(id, !enabled, e.currentTarget);
                            }
                        });
                    });

                    // 添加删除事件
                    document.querySelectorAll('.delete-schedule').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                deleteSchedule(id, e.currentTarget);
                            }
                        });
                    });

                    // 添加执行事件
                    document.querySelectorAll('.execute-schedule').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                executeSchedule(id, e.currentTarget);
                            }
                        });
                    });
                    
                    // 添加详情查看事件
                    document.querySelectorAll('.view-schedule').forEach(btn => {
                        btn.addEventListener('click', (e) => {
                            const id = e.currentTarget.getAttribute('data-id');
                            if (id) {
                                viewScheduleDetails(id);
                            }
                        });
                    });
                }
            }
        }

        // 打开调度编辑模态框
        function openScheduleModal(schedule) {
            const modal = document.getElementById('schedule-modal');
            const modalTitle = document.getElementById('schedule-modal-title');
            const scheduleIdInput = document.getElementById('schedule-id');
            const scheduleNameInput = document.getElementById('schedule-name');
            const scheduleTaskSelect = document.getElementById('schedule-task');
            const scheduleTypeSelect = document.getElementById('schedule-type');
            const scheduleExpressionInput = document.getElementById('schedule-expression');
            const scheduleEnabledCheckbox = document.getElementById('schedule-enabled');

            if (modal && modalTitle && scheduleIdInput && scheduleNameInput && scheduleTaskSelect && 
                scheduleTypeSelect && scheduleExpressionInput && scheduleEnabledCheckbox) {
                
                if (schedule) {
                    modalTitle.textContent = '编辑调度';
                    scheduleIdInput.value = schedule.id;
                    scheduleNameInput.value = schedule.name;
                    scheduleTaskSelect.value = schedule.taskId;
                    scheduleTypeSelect.value = schedule.type;
                    scheduleExpressionInput.value = schedule.expression;
                    scheduleEnabledCheckbox.checked = schedule.enabled;
                } else {
                    modalTitle.textContent = '添加调度';
                    scheduleIdInput.value = '';
                    scheduleNameInput.value = '';
                    scheduleTaskSelect.value = '';
                    scheduleTypeSelect.value = 'cron';
                    scheduleExpressionInput.value = '';
                    scheduleEnabledCheckbox.checked = true;
                }

                modal.classList.remove('hidden');
                scheduleNameInput.focus();
                
                // 更新表达式提示
                updateExpressionFeedback();
                
                // 绑定类型变更事件
                scheduleTypeSelect.addEventListener('change', updateExpressionFeedback);
                
                // 绑定表达式输入事件
                scheduleExpressionInput.addEventListener('input', updateExpressionFeedback);
                
                // 绑定快捷按钮事件
                document.querySelectorAll('.schedule-quick-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const target = e.currentTarget;
                        const quickType = target.getAttribute('data-type');
                        const quickExpression = target.getAttribute('data-expression') || '';
                        
                        scheduleTypeSelect.value = quickType;
                        scheduleExpressionInput.value = quickExpression;
                        updateExpressionFeedback();
                    });
                });
            }
        }

        // 关闭调度编辑模态框
        function closeScheduleModal() {
            const modal = document.getElementById('schedule-modal');
            if (modal) {
                modal.classList.add('hidden');
            }
        }

        // 查看调度详情
        function viewScheduleDetails(id) {
            const schedules = dataStorage.getSchedules();
            const schedule = schedules.find(s => s.id === id);
            if (!schedule) {
                return;
            }
            
            // 获取关联的任务信息
            const tasks = dataStorage.getTasks();
            const task = tasks.find(t => t.id === schedule.taskId);
            
            // 计算下次执行时间
            let nextExecution = "未知";
            try {
                nextExecution = previewNextExecution(schedule.type, schedule.expression);
            } catch (e) {
                console.error("计算下次执行时间失败:", e);
            }
            
            // 格式化时间
            function formatTime(timestamp) {
                if (!timestamp) return "-";
                const date = new Date(timestamp);
                return date.toLocaleString('zh-CN', {
                    year: 'numeric',
                    month: '2-digit',
                    day: '2-digit',
                    hour: '2-digit',
                    minute: '2-digit',
                    second: '2-digit'
                });
            }
            
            // 填充详情信息
            document.getElementById('details-schedule-name').textContent = schedule.name || "-";
            document.getElementById('details-schedule-task').textContent = task ? task.name : "-";
            document.getElementById('details-schedule-type').textContent = schedule.type === 'cron' ? "Cron表达式" : "固定间隔(秒)";
            document.getElementById('details-schedule-expression').textContent = schedule.expression || "-";
            document.getElementById('details-schedule-status').innerHTML = schedule.enabled ? '<span class="text-success font-medium">启用</span>' : '<span class="text-danger font-medium">禁用</span>';
            document.getElementById('details-next-execution').textContent = nextExecution;
            document.getElementById('details-last-execution').textContent = formatTime(schedule.lastExecutionTime);
            document.getElementById('details-created-at').textContent = formatTime(schedule.createdAt);
            document.getElementById('details-updated-at').textContent = formatTime(schedule.updatedAt);
            document.getElementById('details-schedule-description').textContent = schedule.description || "无描述";
            
            // 显示模态框
            const modal = document.getElementById('schedule-details-modal');
            if (modal) {
                modal.classList.remove('hidden');
            }
        }

        // 编辑调度
        function editSchedule(id) {
            const schedules = dataStorage.getSchedules();
            const schedule = schedules.find(s => s.id === id);
            if (schedule) {
                openScheduleModal(schedule);
            }
        }

        // 验证Cron表达式
        function validateCronExpression(expression) {
            // 增强的cron表达式验证，支持5位或6位或7位格式
            const cronPattern = /^\s*((\*\/[0-9]+|[0-9]+(,[0-9]+)*|\*|\?|L|W|C|-|\/|:)\s*){5,7}$/;
            return cronPattern.test(expression);
        }

        // 验证间隔表达式
        function validateIntervalExpression(expression) {
            const num = parseInt(expression);
            return !isNaN(num) && num > 0;
        }

        // 验证调度表达式
        function validateScheduleExpression(type, expression) {
            if (type === 'cron') {
                return validateCronExpression(expression);
            } else {
                return validateIntervalExpression(expression);
            }
        }

        // 计算下次执行时间
        function getNextExecutionTime(type, expression, lastExecutionTime = null) {
            if (type === 'interval') {
                const seconds = parseInt(expression);
                if (!isNaN(seconds) && seconds > 0) {
                    const baseTime = lastExecutionTime ? new Date(lastExecutionTime) : new Date();
                    return new Date(baseTime.getTime() + seconds * 1000);
                }
            } else if (type === 'cron') {
                // 实现简单的cron表达式解析（支持5位格式：分 时 日 月 周）
                return parseCronExpression(expression, lastExecutionTime);
            }
            return null;
        }

        // 解析cron表达式，返回下次执行时间
        function parseCronExpression(expression, lastExecutionTime = null) {
            const parts = expression.trim().split(/\s+/).filter(Boolean);
            if (parts.length !== 5) return null;

            const [minute, hour, day, month, weekday] = parts;
            const now = lastExecutionTime ? new Date(lastExecutionTime) : new Date();
            const next = new Date(now);
            next.setMilliseconds(0);
            next.setSeconds(0);
            next.setMinutes(next.getMinutes() + 1);

            // 简单实现，支持 * 和数值
            // 完整实现应支持范围、间隔、列表等
            while (true) {
                const nMinute = next.getMinutes();
                const nHour = next.getHours();
                const nDay = next.getDate();
                const nMonth = next.getMonth() + 1;
                const nWeekday = next.getDay();

                let match = true;

                // 检查分钟
                if (minute !== '*' && parseInt(minute) !== nMinute) match = false;
                // 检查小时
                if (match && hour !== '*' && parseInt(hour) !== nHour) match = false;
                // 检查日
                if (match && day !== '*' && parseInt(day) !== nDay) match = false;
                // 检查月
                if (match && month !== '*' && parseInt(month) !== nMonth) match = false;
                // 检查周
                if (match && weekday !== '*' && parseInt(weekday) !== nWeekday) match = false;

                if (match) return next;

                // 增加一分钟
                next.setMinutes(next.getMinutes() + 1);

                // 防止无限循环（最多检查一年）
                if (next.getTime() > now.getTime() + 365 * 24 * 60 * 60 * 1000) {
                    return null;
                }
            }
        }

        // 预览下次执行时间
        function previewNextExecution(type, expression) {
            if (type === 'interval') {
                const seconds = parseInt(expression);
                if (!isNaN(seconds) && seconds > 0) {
                    const nextTime = new Date(Date.now() + seconds * 1000);
                    return `下次执行时间: ${formatDateTime(nextTime)}`;
                }
            } else if (type === 'cron') {
                const nextTime = getNextExecutionTime(type, expression);
                if (nextTime) {
                    return `下次执行时间: ${formatDateTime(nextTime)}`;
                } else {
                    return `下次执行时间: 解析失败`;
                }
            }
            return '';
        }

        // 更新表达式提示和预览
        function updateExpressionFeedback() {
            const scheduleTypeSelect = document.getElementById('schedule-type');
            const scheduleExpressionInput = document.getElementById('schedule-expression');
            const expressionHint = document.getElementById('schedule-expression-hint');
            const nextExecutionPreview = document.getElementById('schedule-next-execution');

            if (!scheduleTypeSelect || !scheduleExpressionInput || !expressionHint || !nextExecutionPreview) return;

            const type = scheduleTypeSelect.value;
            const expression = scheduleExpressionInput.value.trim();

            // 更新提示文本
            if (type === 'cron') {
                expressionHint.textContent = 'Cron格式: 秒 分 时 日 月 周 年';
            } else {
                expressionHint.textContent = '固定间隔: 秒数 (必须为正整数)';
            }

            // 验证表达式并显示预览
            if (expression) {
                const isValid = validateScheduleExpression(type, expression);
                
                if (isValid) {
                    expressionHint.classList.remove('text-red-500');
                    expressionHint.classList.add('text-text-secondary');
                    
                    const previewText = previewNextExecution(type, expression);
                    if (previewText) {
                        nextExecutionPreview.textContent = previewText;
                        nextExecutionPreview.className = 'text-xs text-green-600 mt-1';
                        nextExecutionPreview.classList.remove('hidden');
                    }
                } else {
                    expressionHint.classList.remove('text-text-secondary');
                    expressionHint.classList.add('text-red-500');
                    nextExecutionPreview.classList.add('hidden');
                }
            } else {
                expressionHint.classList.remove('text-red-500');
                expressionHint.classList.add('text-text-secondary');
                nextExecutionPreview.classList.add('hidden');
            }
        }

        // 保存调度
        function saveSchedule() {
            const saveBtn = document.getElementById('save-schedule-btn');
            const scheduleIdInput = document.getElementById('schedule-id');
            const scheduleNameInput = document.getElementById('schedule-name');
            const scheduleTaskSelect = document.getElementById('schedule-task');
            const scheduleTypeSelect = document.getElementById('schedule-type');
            const scheduleExpressionInput = document.getElementById('schedule-expression');
            const scheduleEnabledCheckbox = document.getElementById('schedule-enabled');

            if (scheduleNameInput.value.trim() === '') {
                showNotification('请输入调度名称', 'error');
                scheduleNameInput.focus();
                return;
            }

            if (scheduleTaskSelect.value === '') {
                showNotification('请选择关联任务', 'error');
                scheduleTaskSelect.focus();
                return;
            }

            if (scheduleExpressionInput.value.trim() === '') {
                showNotification('请输入调度表达式', 'error');
                scheduleExpressionInput.focus();
                return;
            }

            // 验证表达式
            const type = scheduleTypeSelect.value;
            const expression = scheduleExpressionInput.value.trim();
            
            if (!validateScheduleExpression(type, expression)) {
                showNotification(type === 'cron' ? 'Cron表达式格式不正确' : '间隔秒数必须为正整数', 'error');
                scheduleExpressionInput.focus();
                return;
            }

            // 获取现有调度（保留lastExecutionTime）
            const existingSchedules = dataStorage.getSchedules();
            const existingSchedule = existingSchedules.find(s => s.id === scheduleIdInput.value);

            // 计算下次执行时间
            const nextExecutionTime = getNextExecutionTime(type, expression, existingSchedule?.lastExecutionTime);

            const schedule = {
                id: scheduleIdInput.value || Date.now().toString(),
                name: scheduleNameInput.value.trim(),
                taskId: scheduleTaskSelect.value,
                type: type,
                expression: expression,
                enabled: scheduleEnabledCheckbox.checked,
                createdAt: '', // 会在saveSchedule中设置
                updatedAt: '',  // 会在saveSchedule中设置
                lastExecutionTime: existingSchedule?.lastExecutionTime,
                nextExecutionTime: nextExecutionTime ? nextExecutionTime.toISOString() : null
            };

            // 添加loading状态
            saveBtn.disabled = true;
            saveBtn.classList.add('btn-loading');

            // 添加2秒延迟模拟真实操作
            setTimeout(function() {
                dataStorage.saveSchedule(schedule);
                closeScheduleModal();
                loadSchedules();
                showNotification('调度保存成功', 'success');
                
                // 移除loading状态
                saveBtn.disabled = false;
                saveBtn.classList.remove('btn-loading');
            }, 2000);
        }

        // 切换调度状态
        function toggleScheduleStatus(id, enabled, button) {
            // 添加loading状态
            if (button) {
                button.classList.add('btn-loading');
                button.disabled = true;
            }
            
            // 添加2秒延迟模拟真实操作
            setTimeout(function() {
                dataStorage.updateScheduleStatus(id, enabled);
                loadSchedules();
                
                // 移除loading状态
                if (button) {
                    button.classList.remove('btn-loading');
                    button.disabled = false;
                }
            }, 2000);
        }

        // 删除调度
        function deleteSchedule(id, button) {
            if (confirm('确定要删除这个调度吗？')) {
                // 添加loading状态
                if (button) {
                    button.classList.add('btn-loading');
                    button.disabled = true;
                }
                
                // 添加2秒延迟模拟真实操作
                setTimeout(function() {
                    dataStorage.deleteSchedule(id);
                    loadSchedules();
                    
                    // 移除loading状态
                    if (button) {
                        button.classList.remove('btn-loading');
                        button.disabled = false;
                    }
                }, 2000);
            }
        }

        // 执行调度
        function executeSchedule(id, button) {
            const schedules = dataStorage.getSchedules();
            const schedule = schedules.find(s => s.id === id);
            if (schedule) {
                const tasks = dataStorage.getTasks();
                const task = tasks.find(t => t.id === schedule.taskId);
                if (task) {
                    // 添加loading状态
                    if (button) {
                        button.classList.add('btn-loading');
                        button.disabled = true;
                    }
                    
                    // 添加3秒延迟模拟真实操作
                    setTimeout(function() {
                        try {
                            // 真正执行任务
                            const result = dataStorage.executeTask(schedule.taskId);
                            
                            // 记录调度执行
                            dataStorage.addLog(task.id, task.name, `手动执行调度: ${schedule.name} - 处理了 ${result.totalRecords} 条记录，修复了 ${result.fixedRecords} 条记录`, 'success');
                            
                            // 更新最后执行时间
                            const now = new Date().toISOString();
                            schedule.lastExecutionTime = now;
                            dataStorage.saveSchedule(schedule);
                            
                            showNotification(`调度执行成功: ${schedule.name}，处理了 ${result.totalRecords} 条记录，修复了 ${result.fixedRecords} 条记录`, 'success');
                            
                            // 切换到日志标签页
                            const logsTab = document.getElementById('tab-logs');
                            if (logsTab) {
                                logsTab.click();
                            }
                        } catch (error) {
                            dataStorage.addLog(task.id, task.name, `调度执行失败: ${schedule.name} - ${error.message}`, 'error');
                            showNotification(`调度执行失败: ${error.message}`, 'error');
                        } finally {
                            // 移除loading状态
                            if (button) {
                                button.classList.remove('btn-loading');
                                button.disabled = false;
                            }
                        }
                    }, 3000);
                } else {
                    showNotification('关联任务不存在，无法执行调度', 'error');
                }
            }
        }
        
        // 手动执行任务
        function runTask(id, button) {
            // 添加loading状态
            if (button) {
                button.classList.add('btn-loading');
                button.disabled = true;
            }
            
            // 添加3秒延迟模拟真实操作
            setTimeout(function() {
                try {
                    const task = dataStorage.getTasks().find(t => t.id === id);
                    if (!task) {
                        showNotification('任务不存在', 'error');
                        return;
                    }
                    
                    // 执行任务
                    const result = dataStorage.executeTask(id);
                    
                    showNotification(`任务执行成功: ${task.name}，处理了 ${result.totalRecords} 条记录，修复了 ${result.fixedRecords} 条记录`, 'success');
                    
                    // 切换到日志标签页
                    const logsTab = document.getElementById('tab-logs');
                    if (logsTab) {
                        logsTab.click();
                    }
                    
                    // 重新加载日志
                    loadLogs();
                } catch (error) {
                    showNotification(`任务执行失败: ${error.message}`, 'error');
                } finally {
                    // 移除loading状态
                    if (button) {
                        button.classList.remove('btn-loading');
                        button.disabled = false;
                    }
                }
            }, 3000);
        }
        
        // 显示通知
        function showNotification(message, type = 'info') {
            // 检查是否已存在通知元素
            let notificationEl = document.getElementById('notification');
            
            if (!notificationEl) {
                // 创建通知元素
                notificationEl = document.createElement('div');
                notificationEl.id = 'notification';
                notificationEl.className = 'fixed bottom-4 right-4 px-4 py-3 rounded-md shadow-lg z-50 transition-all duration-300 transform translate-y-10 opacity-0';
                document.body.appendChild(notificationEl);
            }
            
            // 设置通知内容和样式
            notificationEl.textContent = message;
            
            // 根据类型设置样式
            notificationEl.className = 'fixed bottom-4 right-4 px-4 py-3 rounded-md shadow-lg z-50 transition-all duration-300 transform';
            
            if (type === 'success') {
                notificationEl.classList.add('bg-green-100', 'text-green-800', 'border-l-4', 'border-green-500');
            } else if (type === 'error') {
                notificationEl.classList.add('bg-red-100', 'text-red-800', 'border-l-4', 'border-red-500');
            } else {
                notificationEl.classList.add('bg-blue-100', 'text-blue-800', 'border-l-4', 'border-blue-500');
            }
            
            // 显示通知
            notificationEl.classList.remove('translate-y-10', 'opacity-0');
            notificationEl.classList.add('translate-y-0', 'opacity-100');
            
            // 3秒后隐藏通知
            setTimeout(() => {
                notificationEl.classList.remove('translate-y-0', 'opacity-100');
                notificationEl.classList.add('translate-y-10', 'opacity-0');
            }, 3000);
        }

        // 初始化日志
        function initLogs() {
            // 加载日志任务选项
            loadLogTaskOptions();

            // 加载日志
            loadLogs();

            // 日志任务过滤事件
            document.getElementById('log-task-filter')?.addEventListener('change', () => {
                loadFilteredLogs();
            });

            // 日期过滤事件
            document.getElementById('log-date-filter')?.addEventListener('change', () => {
                loadFilteredLogs();
            });

            // 日志级别过滤事件
            document.getElementById('log-level-filter')?.addEventListener('change', () => {
                loadFilteredLogs();
            });

            // 搜索事件
            document.getElementById('log-search')?.addEventListener('input', () => {
                loadFilteredLogs();
            });

            // 清除过滤事件
            document.getElementById('clear-log-filter')?.addEventListener('click', () => {
                document.getElementById('log-task-filter').value = '';
                document.getElementById('log-date-filter').value = '';
                document.getElementById('log-level-filter').value = '';
                document.getElementById('log-search').value = '';
                loadFilteredLogs();
            });

            // 刷新日志事件
            document.getElementById('refresh-logs')?.addEventListener('click', () => {
                loadFilteredLogs();
            });
        }

        // 加载过滤后的日志
        function loadFilteredLogs() {
            const taskId = document.getElementById('log-task-filter').value;
            const date = document.getElementById('log-date-filter').value;
            const level = document.getElementById('log-level-filter').value;
            const searchTerm = document.getElementById('log-search').value.trim();
            
            loadLogs(taskId, date, level, searchTerm);
        }

        // 加载日志任务选项
        function loadLogTaskOptions() {
            const tasks = dataStorage.getTasks();
            const taskSelect = document.getElementById('log-task-filter');

            if (taskSelect) {
                // 保存当前选中的值
                const selectedValue = taskSelect.value;
                
                // 清空现有选项（保留第一个）
                const firstOption = taskSelect.firstElementChild;
                taskSelect.innerHTML = '';
                if (firstOption) {
                    taskSelect.appendChild(firstOption);
                }

                // 添加任务选项
                tasks.forEach(task => {
                    const option = document.createElement('option');
                    option.value = task.id;
                    option.textContent = task.name;
                    taskSelect.appendChild(option);
                });

                // 恢复选中值
                if (tasks.some(t => t.id === selectedValue) || selectedValue === '') {
                    taskSelect.value = selectedValue;
                }
            }
        }

        // 加载日志
        function loadLogs(taskIdFilter, dateFilter, levelFilter, searchTerm) {
            const logs = dataStorage.getLogs();

            // 过滤日志
            let filteredLogs = logs;

            // 任务过滤
            if (taskIdFilter) {
                filteredLogs = filteredLogs.filter(log => log.taskId === taskIdFilter);
            }

            // 日期过滤
            if (dateFilter) {
                filteredLogs = filteredLogs.filter(log => {
                    const logDate = new Date(log.timestamp).toISOString().split('T')[0];
                    return logDate === dateFilter;
                });
            }

            // 日志级别过滤
            if (levelFilter) {
                filteredLogs = filteredLogs.filter(log => log.level === levelFilter);
            }

            // 搜索过滤
            if (searchTerm) {
                const searchLower = searchTerm.toLowerCase();
                filteredLogs = filteredLogs.filter(log => 
                    log.message.toLowerCase().includes(searchLower) || 
                    log.taskName.toLowerCase().includes(searchLower)
                );
            }

            const logsContentEl = document.getElementById('logs-content');

            if (logsContentEl) {
                logsContentEl.innerHTML = '';
                
                if (filteredLogs.length === 0) {
                    const filterApplied = taskIdFilter || dateFilter || levelFilter || searchTerm;
                    logsContentEl.innerHTML = `
                        <div class="text-text-secondary text-center py-12">
                            <i class="fa fa-search text-4xl mb-4 opacity-30"></i>
                            <p>${filterApplied ? '没有找到匹配的日志记录' : '暂无日志记录'}</p>
                            ${filterApplied ? '<p class="text-xs mt-2">请尝试调整过滤条件</p>' : ''}
                        </div>
                    `;
                    return;
                }

                // 显示日志统计
                const statsEl = document.createElement('div');
                statsEl.className = 'flex justify-between items-center text-xs text-text-secondary mb-4 px-2';
                statsEl.innerHTML = `
                    <span>共 ${filteredLogs.length} 条日志记录</span>
                    <span>时间范围: ${formatDate(new Date(filteredLogs[filteredLogs.length-1].timestamp).toISOString().split('T')[0])} - ${formatDate(new Date(filteredLogs[0].timestamp).toISOString().split('T')[0])}</span>
                `;
                logsContentEl.appendChild(statsEl);

                // 按时间倒序排序
                filteredLogs.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
                
                // 按日期分组显示
                const logsByDate = {};
                
                filteredLogs.forEach(log => {
                    const date = new Date(log.timestamp).toISOString().split('T')[0];
                    if (!logsByDate[date]) {
                        logsByDate[date] = [];
                    }
                    logsByDate[date].push(log);
                });

                // 创建日期分组标题和日志条目
                Object.keys(logsByDate).sort((a, b) => new Date(b).getTime() - new Date(a).getTime()).forEach(date => {
                    // 创建日期标题
                    const dateHeader = document.createElement('div');
                    dateHeader.className = 'text-sm font-medium text-text-secondary mb-2 mt-6 first:mt-0 flex items-center';
                    dateHeader.innerHTML = `
                        <div class="w-2 h-2 rounded-full bg-primary mr-2"></div>
                        ${formatDate(date)} (${logsByDate[date].length} 条)
                    `;
                    logsContentEl.appendChild(dateHeader);

                    // 创建日志条目
                    logsByDate[date].forEach(log => {
                        const logEntry = document.createElement('div');
                        logEntry.className = 'mb-2 p-3 rounded-md bg-light card-hover';
                        logEntry.dataset.logId = log.id;

                        // 根据日志级别设置样式
                        let levelClass = '';
                        let iconClass = '';
                        let bgClass = '';
                        
                        switch (log.level) {
                            case 'error':
                                levelClass = 'text-red-500';
                                iconClass = 'fa-exclamation-circle';
                                bgClass = 'bg-red-50/30';
                                break;
                            case 'warning':
                                levelClass = 'text-yellow-500';
                                iconClass = 'fa-exclamation-triangle';
                                bgClass = 'bg-yellow-50/30';
                                break;
                            case 'success':
                                levelClass = 'text-green-500';
                                iconClass = 'fa-check-circle';
                                bgClass = 'bg-green-50/30';
                                break;
                            default:
                                levelClass = 'text-primary';
                                iconClass = 'fa-info-circle';
                                bgClass = 'bg-blue-50/30';
                        }

                        // 格式化时间
                        const time = new Date(log.timestamp).toLocaleTimeString('zh-CN', { 
                            hour: '2-digit', 
                            minute: '2-digit', 
                            second: '2-digit',
                            hour12: false 
                        });

                        logEntry.innerHTML = `
                            <div class="flex justify-between items-start">
                                <div class="flex items-center">
                                    <i class="fa ${iconClass} ${levelClass} mr-2"></i>
                                    <span class="font-medium">${log.taskName || '系统'}</span>
                                    <span class="ml-2 text-xs ${levelClass} px-2 py-0.5 rounded-full ${bgClass}">${getLevelText(log.level)}</span>
                                </div>
                                <div class="flex items-center gap-2">
                                    <span class="text-xs text-text-secondary">${time}</span>
                                    <button class="copy-log-btn text-text-secondary hover:text-primary smooth-transition" title="复制日志">
                                        <i class="fa fa-copy"></i>
                                    </button>
                                </div>
                            </div>
                            <div class="ml-6 mt-2 text-sm whitespace-pre-wrap">${escapeHtml(log.message)}</div>
                        `;

                        // 添加复制功能
                        const copyBtn = logEntry.querySelector('.copy-log-btn');
                        if (copyBtn) {
                            copyBtn.addEventListener('click', (e) => {
                                e.stopPropagation(); // 防止触发日志条目点击事件
                                navigator.clipboard.writeText(log.message).then(() => {
                                    showNotification('日志内容已复制', 'success');
                                }).catch(() => {
                                    showNotification('复制失败，请手动复制', 'error');
                                });
                            });
                        }

                        // 添加点击查看详情功能
                        logEntry.addEventListener('click', () => {
                            viewLogDetails(log);
                        });

                        logsContentEl.appendChild(logEntry);
                    });
                });
            }
        }

        // 获取日志级别文本
        function getLevelText(level) {
            switch (level) {
                case 'error': return '错误';
                case 'warning': return '警告';
                case 'success': return '成功';
                default: return '信息';
            }
        }

        // HTML转义函数
        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        // 格式化日期
        function formatDate(dateString) {
            const today = new Date();
            today.setHours(0, 0, 0, 0);
            
            const yesterday = new Date(today);
            yesterday.setDate(yesterday.getDate() - 1);
            
            const date = new Date(dateString);
            date.setHours(0, 0, 0, 0);
            
            if (date.getTime() === today.getTime()) {
                return '今天';
            } else if (date.getTime() === yesterday.getTime()) {
                return '昨天';
            } else {
                return date.toLocaleDateString('zh-CN');
            }
        }

        // 格式化日期时间
        function formatDateTime(dateString) {
            const date = new Date(dateString);
            return date.toLocaleString('zh-CN', { 
                year: 'numeric', 
                month: '2-digit', 
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit'
            });
        }

        // 查看日志详情
        function viewLogDetails(log) {
            // 设置日志级别样式
            let levelClass = '';
            let levelText = '';
            
            switch (log.level) {
                case 'error':
                    levelClass = 'text-red-500 font-medium';
                    levelText = '错误';
                    break;
                case 'warning':
                    levelClass = 'text-yellow-500 font-medium';
                    levelText = '警告';
                    break;
                case 'success':
                    levelClass = 'text-green-500 font-medium';
                    levelText = '成功';
                    break;
                default:
                    levelClass = 'text-primary font-medium';
                    levelText = '信息';
            }
            
            // 填充详情信息
            document.getElementById('details-log-task').textContent = log.taskName || '系统';
            document.getElementById('details-log-level').innerHTML = `<span class="${levelClass}">${levelText}</span>`;
            document.getElementById('details-log-time').textContent = formatDateTime(log.timestamp);
            document.getElementById('details-log-id').textContent = log.id;
            document.getElementById('details-log-message').textContent = log.message;
            
            // 显示模态框
            const modal = document.getElementById('log-details-modal');
            if (modal) {
                modal.classList.remove('hidden');
            }
        }

        // 初始化调度详情模态框
        function initScheduleDetailsModal() {
            // 关闭调度详情模态框
            document.getElementById('close-schedule-details-modal').addEventListener('click', function() {
                document.getElementById('schedule-details-modal').classList.add('hidden');
            });
            
            document.getElementById('close-schedule-details-btn').addEventListener('click', function() {
                document.getElementById('schedule-details-modal').classList.add('hidden');
            });
            
            // 点击模态框外部关闭
            document.getElementById('schedule-details-modal').addEventListener('click', function(e) {
                if (e.target === this) {
                    this.classList.add('hidden');
                }
            });
        }

        // 初始化日志详情模态框
        function initLogDetailsModal() {
            // 关闭日志详情模态框
            document.getElementById('close-log-details-modal').addEventListener('click', function() {
                document.getElementById('log-details-modal').classList.add('hidden');
            });
            
            document.getElementById('close-log-details-btn').addEventListener('click', function() {
                document.getElementById('log-details-modal').classList.add('hidden');
            });
            
            // 点击模态框外部关闭
            document.getElementById('log-details-modal').addEventListener('click', function(e) {
                if (e.target === this) {
                    this.classList.add('hidden');
                }
            });
            
            // 复制完整日志
            document.getElementById('copy-log-details-btn').addEventListener('click', function() {
                const message = document.getElementById('details-log-message').textContent;
                const taskName = document.getElementById('details-log-task').textContent;
                const level = document.getElementById('details-log-level').textContent;
                const time = document.getElementById('details-log-time').textContent;
                const id = document.getElementById('details-log-id').textContent;
                
                const fullLog = `${time} [${level}] [${taskName}] [ID: ${id}]\n${message}`;
                
                navigator.clipboard.writeText(fullLog).then(() => {
                    showNotification('完整日志已复制', 'success');
                }).catch(() => {
                    showNotification('复制失败，请手动复制', 'error');
                });
            });
        }

        // 初始化应用
        function initApp() {
            // 初始化示例数据
            initializeSampleData();
            
            // 初始化各功能模块
            initTabs();
            initTaskManagement();
            initTaskScheduling();
            initLogs();
            initRuleBuilder(); // 初始化规则构建器
            initScheduleDetailsModal(); // 初始化调度详情模态框
            initLogDetailsModal(); // 初始化日志详情模态框
        }

        // 页面加载完成后初始化应用
        document.addEventListener('DOMContentLoaded', initApp);
    </script>
</body>
</html>